Joshua Richardson
Joshua Richardson

Reputation: 115

Typescript function arguments proper value type of object

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

Answers (1)

Nishant
Nishant

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

Related Questions