Is there a way to dynamically pick a type from interface in typescript

as the title says, I tried to dynamically get the type from interface based on the key I receive in a function.

Example:

interface State {
    foo: boolean;
    bar: string;
    baz: number;
}

const globalState: State = {
    foo: true,
    bar: 'somethin',
    baz: 42,
}

const update = (key: keyof State, newValue: /* TYPE ME PLZ */): State => {
    globalState[key] = newValue;
    return globalState;
}

Unfortunately, this causes error Type '<INSERTED_TYPE>' is not assignable to type 'never'

The closest I got is something like this State[keyof State], but is it totally unrelated to the key I receive in the function.

My question: Is there a way to get the type of the newValue parameter?

Bonus question: Why is the type in the error message never?

Upvotes: 1

Views: 1062

Answers (1)

Aleksey L.
Aleksey L.

Reputation: 37918

You can use generics for this:

const update = <K extends keyof State>(key: K, newValue: State[K]): State => {
    globalState[key] = newValue;
    return globalState;
}

update('foo', true); // OK
update('foo', 1); // Error: Argument of type '1' is not assignable to parameter of type 'boolean'

Now newValue type is resolved according to key type.

Playground

Upvotes: 1

Related Questions