Let& #39;s dig in. Gary& #39;s discovery is thankfully easy to reproduce

let b: 1 | 2 = 3;

This indeed produces the error (under --target ES5)

Type & #39;3& #39; is not assignable to type & #39;1 | 2& #39;.

and with --target ES6:

Type & #39;3& #39; is not assignable to type & #39;2 | 1& #39;.

Cool, what the heck? https://twitter.com/garybernhardt/status/1311419940168060929">https://twitter.com/garybernh...
First, background. TypeScript aggressively interns types during checking to save memory and improve performance. This means that there& #39;s only ever one type object (the internal representation) for the literal & #39;1& #39; and only ever one type object for the literal & #39;2& #39;
Each type is assigned an incrementing ID when it& #39;s created. The order in which types are created is basically the order in which they are depth-first encountered when checking the entire program tree.
This is depth-first from the perspective of "What types are needed to check this line of code". This means a type that is declared much later in a file might still have a lower ID than an earlier-declared type if it ends up being resolved first due to forward references to it
The net result is that type ID ordering is deterministic, but not predictable. It& #39;s effectively chaotic - small changes in the input can have nearly arbitrarily large effects on which types get which IDs. Assuming everything& #39;s going well, though, IDs are not user-observable
Now, union types are stored as a sorted list of constituent types, where the sort key is type ID. This is fine because unions are inherently not ordered at all; any two orderings of a union should behave identically (minus some *really* bad edge cases I will not tell you about).
Representing them in sorted order makes ops like identical-to, superset-of, and subset-of linear, which is nice. This is also why you should never even think about trying to "convert" a union type to a tuple type of its constituents; stop asking for this!
The printback order is this same order. For any type that isn& #39;t string or numeric literals, there& #39;s no natural ordering of types anyway, so this doesn& #39;t really matter. Probably we should sort literals on printback to stop this weirdness, but eh, then what would I tweet about
Anyway what we can learn from this is that something in the higher ES libs instantiated the & #39;2& #39; type before the & #39;1& #39; type. Where, though? May as well attach a debugger here to a copy of tsc.js with a hacked conditional breakpoint in the area of interest.
Sure enough, we hit this on & #39;2& #39; first when target = ES6. Where? In a situation like this, you want to go up the callstack until a node is in scope (at getTypeFromTypeNode), and inspect it.
Run stuff like this in your debug console

node.__debugGetText()
> "[K, V]"
node.parent.parent.__debugGetText()
> "[Symbol.iterator](): IterableIterator<[K, V]>;"

TypeScript is creating the tuple type [K, V] and creating the literal type 2 for its length property.
Symbol.iterator comes from the ES6 lib files (since it& #39;s an ES6 feature), which is why 2 is first in ES6 but not in ES5 https://abs.twimg.com/emoji/v2/... draggable="false" alt="⭐" title="Mittelgroßer Stern" aria-label="Emoji: Mittelgroßer Stern">
& #39;1& #39; gets created later, from this type in lib.dom.d.ts

interface CountQueuingStrategy extends QueuingStrategy {
highWaterMark: number;
size(chunk: any): 1; <--
}

This is also the first & #39;1& #39; under ES5; the first 2 in ES5 is from a length-2 tuple in ReadableStream& #39;s & #39;tee& #39;
With this information, a hypothesis: Enabling skipLibCheck should go back to the other order, because none of the stuff in the lib should get checked before the usercode?

tsc --skipLibCheck --target ES6 sample.ts
error TS2322: Type & #39;3& #39; is not assignable to type & #39;1 | 2& #39;

https://abs.twimg.com/emoji/v2/... draggable="false" alt="🚀" title="Rakete" aria-label="Emoji: Rakete">
You can follow @SeaRyanC.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled: