3

I am trying to assign a value from an object of type TestInterface to another object of type TestInterface by accessing it with a dynamic key of type keyof TestInterface. However typescript seems to forget that this key is the same on both instances and therefore throws an error.

Since this sentence is hard to read, here is an example:

interface TestInterface {
    testKey?: NestesOptInterface;
    optKey?: string;
}

interface NestesOptInterface {
    key1?: string;
    key2?: string
}

const myObj : TestInterface= {

}

const myObj2 : TestInterface = {
    testKey: {
        key1: "test",
    }
}

const attributes : string[] = ['testKey', 'optKey']

const myTestKey: keyof TestInterface = attributes[0] as keyof TestInterface

/**Type 'string | NestesOptInterface | undefined' is not assignable to type '(NestesOptInterface & string) | undefined'.
 * Type 'NestesOptInterface' is not assignable to type 'NestesOptInterface & string'.
 * Type 'NestesOptInterface' is not assignable to type 'string'.(2322)**/
myObj[myTestKey] = myObj2[myTestKey]

//does work (obviously)
myObj['testKey'] = myObj2['testKey']

The tricky part is that testKey in the assignment of myTestKey should actually be any value of type string.

I was wondering whether this is a bug or how I can do this properly? Here is the Link to the Typescript Playground.

Robert Haslinger
  • 155
  • 1
  • 17
  • You can only pass a string to get a specific property. You cannot pass an object. That's why typescript shows that error, because `keyof TestInterface` could also be having the type `NestesOptInterface` and obviously you can't pass an object as property name. The weird thing is however that the error shows only to the assigned object (left one) even if you change that, the assigned one would only get the error. I would have expected to see an error on both of them. – MrJami May 06 '22 at 10:52
  • Isn't keyof TestInterface only equivalent to "testKey" and "optKey" and therefore a string? I do not believe that this is the issue here. – Robert Haslinger May 06 '22 at 11:11
  • True. You are right, it should be a string. It could be a bug. Consider opening a ticket in the TypeScript community. Because right now, Typescript gives the key the type of all possible values of the possible keys. And then it conflicts with the object method I mentioned. – MrJami May 06 '22 at 14:00

2 Answers2

3

I managed to find a not-too-dirty workaround that works for my use case. See example below:

//solution
myObj = {
    ...myObj,
    [myTestKey]: myObj2[myTestKey]
}

Note: myObj is now let instead of const

Typescript Playground

Robert Haslinger
  • 155
  • 1
  • 17
0

You need to add type as -

const myTestKey: keyof TestInterface = 'testKey';

Playground

dhaker
  • 1,605
  • 18
  • 19
  • This does indeed solve the example, however - and I will edit my question accordingly - in my use case, `testKey` in the assignment actually represents just a value of type string, therefore I can not type the const explicitly. – Robert Haslinger May 06 '22 at 11:55