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 !
>Solution :
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.