Issue
Why S
is string
in following code?
type T<X> = {[K in keyof X]: never};
type S = T<string>;
Here is TypeScript playground. https://www.typescriptlang.org/play?#code/C4TwDgpgBAKgPADQHxQLxQN4G0DSUCWAdlANYQgD2AZlAgLoBcUhEAbhAE4C+A3AFChIUAMppYcAM7AORAOZIeQA
It becomes the same type (string
) even if I replace never
by other types.
Adding context, following type works as I expect.
type T<X> = {[K in (keyof X) & string]: never};
type S = T<string>;
Solution
Essentially what you are doing is mapping the keys of the type string
which are number | typeof Symbol.iterator | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" ...
etc. set their types to never
. You can do that with a simple Union.
type X = keyof string; // type X = number | typeof Symbol.iterator | "toString" ...
But not with key mapping the way you tried. What you created is a so called homomorphic mapped type. That means the compiler regognizes you are trying to map the keys of an already existing object type. When that is the case the compiler simple returns a type with the exact same property modifiers as the one on your input type.
In short, when mapping the properties of a primitive type typescript will just return that very primitive type.
This mapped type returns a primitive type, not an object type. Mapped types declared as
{ [ K in keyof T ]: U }
whereT
is a type parameter are known as homomorphic mapped types, which means that the mapped type is a structure preserving function ofT
. When type parameterT
is instantiated with a primitive type the mapped type evaluates to the same primitive. - TypeScript FAQ Bugs that aren't Bugs
Answered By - Behemoth
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.