effective-typescript icon indicating copy to clipboard operation
effective-typescript copied to clipboard

The display of types

Open utterances-bot opened this issue 2 years ago • 4 comments

The display of types

Effective TypeScript: The display of types

https://effectivetypescript.com/2022/02/25/gentips-4-display/

utterances-bot avatar Apr 16 '22 09:04 utterances-bot

type Resolve<T> = T extends Function ? T : {[K in keyof T]: T[K]} seems to be able to preserve types like number or "42":

type n = Resolve<number> // number
type s42 = Resolve<"42"> // "42"

How is that even possible? Ahah I mean {[K in keyof "42"]: "42"[K]} is definitely not the same as "42".

jfet97 avatar Apr 16 '22 09:04 jfet97

It is surprising, isn't it? One clue is that keyof gives the methods defined on the wrapper types for primitives:

type K = keyof number;
//   ^? type K = "toString" | "toFixed" | "toExponential" | ...

But still, I think this must be special-cased in the TypeScript compiler. Especially in the case of a literal type, the result is much more specific than you'd expect. Resolve is magical indeed!

danvk avatar Apr 17 '22 13:04 danvk

I think I found something: https://github.com/microsoft/TypeScript/pull/12447 {[K in keyof T]: T[K]}is what we now call a homomorphic (previously isomorphic) mapped type, and ahejlsberg said that "when a primitive type is substituted for T in an isomorphic mapped type, we simply produce that primitive type".

jfet97 avatar Apr 21 '22 19:04 jfet97

So there is a rationale behind this. Nice find @jfet97! It's news to me that "distributing over unions" is a concept that predates conditional types. This behavior was never mentioned in the release notes at the time (2.1 and 2.2).

danvk avatar Apr 23 '22 13:04 danvk