Typescript: Casting array to union + mapped array types not preserving type order

Created on 7 May 2019  ·  1Comment  ·  Source: microsoft/TypeScript


TypeScript Version: 3.4.0-dev.201xxxxx


Search Terms:

Mapped types key order lost

Code

type Initial = [1, 2, 3, 4]

type FindReplace<T extends any[], Find, Replace> = {
  [K in keyof T]: T[K] extends Find ? Replace : T[K]
}

// Map over array and replace '2'
type ResultArray = FindReplace<Initial, 2, 'was 2'>
// => [1, "was 2", 3, 4]

// Now accessing the array values using [number], the type
// order is lost. This matters because now when the union is later
// cast as a intersection, the types are in the wrong order
type Result = ResultArray[number]
// => 1 | 3 | 4 | "was 2

Expected behavior:

Mapping over types should preserve the key order

Actual behavior:

Mapping over types preserves the "type", but the key order is lost when performing T[keyof T] operator

Related Issues:

Question

Most helpful comment

Union order is not something that you should count on for anything. @RyanCavanaugh mentioned this when unions to tuples were discusses here:

First, union order is not something we can ever allow to be observable. Internally, unions are stored as a sorted list of types (this is the only efficient way to quickly determine relationships between them), and the sort key is an internal ID that generated incrementally. The practical upshot of this is that two extremely similar programs can generate vastly different union orderings, and the same union observed in a language service context might have a different ordering than when observed in a commandline context, because the order in which types are created is simply the order in which they are checked.

>All comments

Union order is not something that you should count on for anything. @RyanCavanaugh mentioned this when unions to tuples were discusses here:

First, union order is not something we can ever allow to be observable. Internally, unions are stored as a sorted list of types (this is the only efficient way to quickly determine relationships between them), and the sort key is an internal ID that generated incrementally. The practical upshot of this is that two extremely similar programs can generate vastly different union orderings, and the same union observed in a language service context might have a different ordering than when observed in a commandline context, because the order in which types are created is simply the order in which they are checked.

Was this page helpful?
0 / 5 - 0 ratings