Reputation: 642
TypeScript supports conditional types, using 'extends' keyword and ternary operators.
Example conditional types that eval to true:
type C1 = 7 extends number ? true : false
type C2 = 7 extends number | string ? true : false
type C3 = 7 extends 7 | 'cat' | null ? true : false
type C4 = [1,2,3] extends [1,2,3] ? true : false
type C5 = any[] extends any[] ? true : false
I understand the conditions above (even if 'extends' seems odd in a non-OOP context).
The following conditions I don't understand:
type Q1 = any[] extends readonly any[] ? true : false // evals to true
type Q2 = readonly any[] extends any[] ? true : false // evals to false
Why does Q1 evaluate to true, and Q2 evaluate to false? I expected the opposite, as the readonly array seems 'more specific' than the general array.
What does 'extends' really mean in this context?
I am using TypeScript Playground to test these conditions.
Upvotes: 4
Views: 1374
Reputation: 2897
It's definitely confusing.
Expected behavior
type A = 'readable'|'mutable' extends 'readable' ? true : false; // false
type B = 'readable' extends 'readable'|'mutable' ? true : false; // true
The way I made any sense was to walk through assigning things.
const C = [1]; // inferred as Array<number>
const D:ReadonlyArray<number> = C; // declare that the mutable array is readonly
const E:Array<number> = D; // error when assigning a ReadonlyArray to Array.
The error seems arbitrary. It could have been that C wasn't assignable to D.
My guess is that they went with it because of historical code in the parser. When parsing a file with something like const F:ReadonlyArray<number> = [1]
, [1] is probably first inferred as Array. They needed a way to declare an already-inferred mutable array as readonly. Hence, Array is assignable to ReadonlyArray.
That sort of makes sense, though feels like a shortcut to get around rewriting the parser.
Upvotes: 0
Reputation: 70307
extends
means "is a subtype of". Nothing more and nothing less. And "A
is a subtype of B
" means "every instance of A
is assignable to a variable of type B
". Again, nothing more and nothing less.
So the only question we need to ask is: is a T[]
assignable to readonly T[]
? Well, readonly T[]
allows us to access the elements of the array. T[]
allows us to access the elements of an array and also to mutate it. So T[]
supports all of the operations of readonly T[]
and then some. Hence, the relationship holds.
Upvotes: 6