Repository navigation
Conditional type is deferred because narrow-as-assertion on constrained type parameter has no effect #29939
Description
Activity
- changed the title
[-]Conditional type is deferred because narrow-as-assertion on constrained type parameter has no affect[/-][+]Conditional type is deferred because narrow-as-assertion on constrained type parameter has no effect[/+]on Feb 16, 2019 jack-williams commented
on Feb 19, 2019 CollaboratorAuthorMore actionsI understand why type parameter constraints are ignored by the restrictive instantiation. Using transitive reasoning with
anybreaks a whole load of things, as shown from the example inchecker.ts.type Foo<T extends { x: any }> = T extends { x: string } ? string : number
A question I have is: are there other examples that do not involve
any, where ignoring constraints is necessary? I can think of another one:type Bar<T extends Object> = T extends object ? string : number
Would it be fair to say that the restrictive instantiation is currently necessary purely because conditional type resolution uses assignability, a non-transitive relation?
I know that
definitelyAssignablewas a thing at one point; was that crafted with the intent to be a transitive type relation?- addedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Feb 19, 2019 jack-williams commented
on Aug 28, 2019 CollaboratorAuthorMore actionsI think I know enough about this now to say that it's a design limitation.
- It is correct that a type parameter
T extends stringdoes not get narrowed toT & stringupontypeofbecause the intersection adds no information: the type parameter is already a subtype ofstring. - The only other vector of change would be to consider constraints in conditional types but there are multiple reasons why this is difficult (and incorrect in some cases).
This leads me to the conclusion that this is just an awkward composition of concepts, but one that few people seem to face.
Reacted by Leon- It is correct that a type parameter
- addedDesign LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixedand removedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Aug 28, 2019 I think I know enough about this now to say that it's a design limitation.
* It is correct that a type parameter `T extends string` does not get narrowed to `T & string` upon `typeof` because the intersection adds no information: the type parameter is already a subtype of `string`. * The only other vector of change would be to consider constraints in conditional types but there are multiple reasons why this is difficult (and incorrect in some cases).This leads me to the conclusion that this is just an awkward composition of concepts, but one that few people seem to face.
Jack Williams (@jack-williams) Would be really great to learn something here. Currently I'm trying to use a conditional type as return type of a function. Inside the function I'm narrowing down on the constraints of the conditional type to return the corresponding value (similar to this SO post.
As I read your posts here I'm wondering about the square bracket notation in your
IsStringtype. What does it do?And you wrote considering constraints in conditional types would sometimes be incorrect. I assume this is the reason why writing a function with conditional return type is not possible. Right? And could you explain why?
Sorry for the gratuitous title.
Code
Expected behavior:
The two to behave the same; probably, they should both be OK.
Actual behavior:
The type of
xdoes not get narrowed by assertion, presumably because the assertion adds no information. Conditional type resolution ignores parameter constraints when attempting to resolve using the most restrictive instantiation, and thereforeIsString<typeof x>does not resolve.Essentially
T extends string, andT & stringwhereTis unconstrained, do not behave the same in conditional check types. The former has its constraint ignored, while the latter gets to use its intersection proof.Playground Link: link
Related Issues: