Home > Enterprise >  TypeScript indexed property not matching inferred generic type
TypeScript indexed property not matching inferred generic type

Time:01-20

This code fails to compile:

type Validator<T> = (value: string) => { value: T }

const createValidator = <TState extends any>(state: TState) =>
    <TName extends keyof TState>(x: TName, validator: Validator<TState[TName]>) => {
        return (value: { [P in TName]: string }): { [P in TName]: TState[TName] } => {
            const result = validator(value[x]);

            return { [x]: result.value };
        };
    }

return { [x]: result.value }; gives me Type '{ [x: string]: TState[TName]; }' is not assignable to type '{ [P in TName]: TState[TName]; }'. even though TName is inferred from x.

Why is that? And what can I do about it - except from casting the returned value?

CodePudding user response:

The problem here is, that TypeScript doesn't infer index signatures in object literals with computed properties. The most minimal example:

type KEY = 'foo' | 'bar';
let obj = { ['foo' as KEY]: 1 };

// obj is of type: { [x: string ]: number }
// and NOT the { foo: number, bar: number }
// and NOT the Record<'foo'|'bar', number>

So in your example you should cast, and to make it simpler, reuse types from variables to not repeat yourself:

return { [x]: result.value } as Record<typeof x, typeof result.value>;
  • Related