Home > Enterprise >  Index Types not Inferring in Typescript
Index Types not Inferring in Typescript

Time:09-26

I have a small code where TS drives me crazy...

type MyCustomType<T extends Record<string, string>> = {
  key: keyof T;
};

export const myFunction = <T extends Record<string, string>>(variable: MyCustomType<T>) => {
  const newVar: string = variable.key;
};

Typescript keeps complaining that variable.key can be string | number | symbol and can't be assign to newVar. But I typed my generic object as Record<string, string>.

So, why TS can't guess it's a string ?

How can I type these, without using as

Thanks a lot !

CodePudding user response:

The compiler does not infer keyof T to be string because it does not have to be a string. Your constraint merely states that every string key must have a string value. But T might also have number or symbol keys.

myFunction<Record<0, string>>({ key: 0 })
// no error, the constraint is fulfilled

So we should explicitly forbid number and symbol keys.

type MyCustomType<
  T extends Record<string, string> 
    & Record<number | symbol, never>
> = {
  key: keyof T & string;
};

export const myFunction = <
  T extends Record<string, string> 
    & Record<number | symbol, never>
>(variable: MyCustomType<T>) => {
  const newVar: string = variable.key;
  console.log(newVar)
};

This still does not silence the error. TypeScript is not able to deduct that keyof T is a string. After all, it could still have number properties of type never (which practically is not possible but you could still explicitly pass a type containing never values). But we can now "safely" intersect keyof T with string.

Playground

  • Related