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
.