I have an type like the follow example
export type Signals = {
activity: boolean;
quest: string;
creator: number;
}
With this type i would get an function that has followed properties
export function initStation<T>(){
return {
signal: (id: keyof T, value: T[keyof T]){
// code
}
}
}
But when i use this implemetation i have all the time an union type vor the value argument. Even when the id argument is setted as activity, quest or creator.
I try to get a better support, when the id is for example equal activity then the possible type is just a boolean, cause in my type above is activity defined as boolean.
I expected to call my function like
const station = initStation<Signals>()
station.signal('activity', true); // fine
station.signal('quest', 'any quest'); // fine
station.signal('creator', 1234); // fine
and getting error when i try to use the function like below
station.signal('activity', 'abc'); // error
station.signal('quest', 123); // error
station.signal('creator', true); // error
CodePudding user response:
If id
is of type keyof T
and value
is of type T[keyof T]
, then they will both be uncorrelated union types and nothing will stop someone from passing in an id
and a value
corresponding to different properties from T
. One way to fix this is to make your method generic in the type of id
, K extends keyof T
, and then have value
represented in terms of that:
export function initStation<T>() {
return {
signal: <K extends keyof T>(id: K, value: T[K]){
// code
}
}
}
This gives you the behavior you desire:
const station = initStation<Signals>();
station.signal('activity', true); // fine
station.signal('quest', 'any quest'); // fine
station.signal('creator', 1234); // fine
station.signal('activity', 'abc'); // error
station.signal('quest', 123); // error
station.signal('creator', true); // error