Reputation: 33
Let me explain what I am trying to achieve and what is the problem.
I have the following interface:
interface ExampleInterface {
a: string;
b: number;
}
I have the following variable which implements my ExampleInterface
:
const exampleVariable: ExampleInterface = {
a: 'hello world',
b: 0,
}
I have the following function which has to modify my exampleVariable
, this function takes two params, the first param has to be a key of exampleVariable
, the second param has to be a new value which I want to assign to the given key(which is passed as a first param):
const setState = (key, value) => {
exampleVariable[key] = value;
}
What I want to achieve is the following:
I want to make sure that if I pass a key equal to a
as a first param, then Typescript won't let me to pass anything except value of type string
because inside ExampleInterface
type of a
is equal to string
.
What I tried to do:
I tried to add the following types for my function params:
const setState = (key: keyof ExampleInterface, value: ExampleInterface[keyof ExampleInterface]) => {
exampleVariable[key] = value;
}
But I keep getting the following Typescript error:
Type 'ExampleInterface[keyof ExampleInterface]' is not assignable to type 'string & number'.
Type 'string' is not assignable to type 'string & number'.
Type 'string' is not assignable to type 'number'.ts(2322)
I assume that types for the function params are not set correctly. Any advice is appreciated. Thank you.
Upvotes: 3
Views: 979
Reputation: 4581
I think this is what you are looking for:
interface ExampleInterface {
[key: string]: number;
}
const exampleVariable: ExampleInterface = {
['hello world'] : 0,
}
console.log(exampleVariable)
const setState = (key: string, value: number) => {
exampleVariable[key] = value;
}
setState('hello world', 1);
console.log(exampleVariable)
Take a look to index signatures for better understanding.
If in the setState you want to refer to the interface types through the interface, this is also valid:
const setState = (keyArg: keyof ExampleInterface, value: ExampleInterface['key']) => {
exampleVariable[keyArg] = value;
}
That is the syntax you were close to.
Upvotes: 0
Reputation: 579
The error is because you specified the key parameter as key of ExampleInterface and it has 2 data types i.e., string and number. KeyOf apply both the data type to the variable passed which voilates the rules of assigning a data type. So you have the extend the keyOf to generic, when you extend and apply the type to the value it maps to the correct type of the key.
Below is the fix for your code.
setState<K extends keyof ExampleInterface>(key: K, value: ExampleInterface[K]){
this.exampleVariable[key] = value;
}
But you could rewrite your code to set the value for generic type, below is the example.
setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
obj[key] = value;
}
Reference: TypeScript:Handbook
Upvotes: 2