Advanced Types - Conditional Types Example
Opened this issue · 2 comments
The following code is shown as an example of types that are immediately resolved:
declare function f<T extends boolean>(x: T): T extends true ? string : number;
// Type is 'string | number
let x = f(Math.random() < 0.5)
However, x can not be assigned a type of string
, e.g. the following throws an error:
let x : string = f(Math.random() < 0.5) // Error: Type 'string | number' is not assignable to type 'string'
Does this not make the conditional type deferred, and not immediately resolved?
However, x can not be assigned a type of string, e.g. the following throws an error:
This is correct behaviour. You don't know if Math.random() < 0.5
will return true of false until runtime, so it is not safe to pick a specific branch in the conditional type.
Does this not make the conditional type deferred, and not immediately resolved?
Deferred means that the conditional type is kept around, rather than squashed to some combination of the branches. As the result type is a union of the branches it has been resolved to some safe approximation.
I think I understand it better now. Still the following seems a bit confusing:
When T or U contains type variables, whether to resolve to X or Y, or to defer, is determined by whether or not a the type system has enough information to conclude that T is always assignable to U.
Please correct me if I'm wrong, but isn't it better explained like this:
When T or U contains type variables, the conditional type is resolved immediately if the type system has enough information to conclude that either T is always assignable to U (will pick a branch) or it is not possible to make such a conclusion until runtime (will resolve to union of the types). In other cases, the conditional type is deferred.