Reputation: 115
I'm having a bit of trouble getting they type assertions I'd like to have.
I have a function
const setSetting: SetSettingFn = (key, value) => {
if (typeof settings[key] != null) {
settings = {
...settings,
[key]: value
}
}
}
with the SetSettingFn type of:
type SetSettingFn = (key: keyof AppSettings, value: AppSettings[keyof AppSettings]) => void
I'd like the value prop to know, based on the key that was entered the proper type to assert from that key. The above just kind of mashes all the types in AppSettings
into one flat type with everything.
For example if settings.foo is boolean, then this should throw a type error:
setSetting('foo', 1)
Upvotes: 2
Views: 174
Reputation: 55866
When you say, AppSettings[keyof AppSettings]
you are allowing any key to be selected from AppSettings
. You need to tell TypeScript that you mean the specific key that is the first parameter to be used to ascertain the value type. Something like this:
let settings: Record<string, any> = {};
const setSetting: SetSettingFn = (key, value) => {
if (typeof settings[key] != null) {
settings = {
...settings,
[key]: value
}
}
}
type AppSettings = {
foo: string;
bar: number;
}
type SetSettingFn = < K extends keyof AppSettings = keyof AppSettings>(key: K, value: AppSettings[K]) => void
setSetting('foo', 1);
// Error: Argument of type 'number' is not assignable to parameter of type 'string'.(2345)
setSetting('foo', 'string');
// OK
Link to TS Playground: https://tsplay.dev/NDzv4W
Upvotes: 1