Closed as not planned
Description
Acknowledgement
- I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.
Comment
Let's consider this Prettify
type:
type Prettify<T extends object> = T extends Function
? T
: { [P in keyof T]: T[P] };
There are two key things to note:
T
has a constraint ofobject
.- The mapped type
{ [P in keyof T]: T[P] }
is homomorphic, so it should preserve the array structure in case of instantiations with arrays. So, for example,Prettify<[string, string]>
returns[string, string]
.
Now, let's consider this instantiation of Prettify
:
// Here, `T` is not constrained with `object`, so we take intersection with `object`
type Test<T> = Prettify<T & object>;
type T1 = Test<[string, string]>;
// ^? type T1 = { [x: number]: string; 0: string; 1: string; length: 2; toString: () => string; toLocaleSt…
I'd expect T1
to be [string, string]
but instead the array structure is lost.
Looks like this happens because of the object
intersection:
type T1 = Prettify<[string, string] & object>;
// ^? type T1 = { [x: number]: string; 0: string; 1: string; length: 2; toString: () => string; toLocaleSt…
The example above might be a bit contrived, but this is a common use case—we have object
constraints at certain places and to satisfy those constraints we often have to take intersections with object
.