You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Constraints applied by conditional types not considered when checking signatures #22347
changed the title [-]Constraints applied by conditional types not considered when checking signatures[/-][+]Constraints applied by conditional types not considered later in control flow[/+]on Mar 6, 2018
changed the title [-]Constraints applied by conditional types not considered later in control flow[/-][+]Constraints applied by conditional types not considered when checking signatures[/+]on Mar 6, 2018
This is actually working as intended. The constraint added to T by the T extends string check is in effect only in the true branch of the conditional type. The T produced by EqString<T> is exactly the same T as was passed in and it doesn't have any new constraints. To get the desired effect you need to return an intersection type:
Hm. OK. That's not the greatest in the context of using conditionals for control flow narrowing, since it causes you to get intersections instead of constrained generics like you'd expect.
Erm, doesn't check out too well, in heavy use practice. It may give the result a new constraint on whatever you say, but it forgets its relationship with the original T, which is bad:
declarefunctionlog(msg: string): voidtypeMustBeString<Textendsstring>=T;typeEQString<T>=TextendsMustBeString<infer U> ? U : neverfunctionc<T>(x: T|string){consty=xasEQString<T>// assert stringinessreturnuseStringyT(y);/// Noooooooo: Argument of type 'EQString<T>' is not assignable to parameter of type 'T & string'functionuseStringyT(x: T&string){return0;}}
sigh just intersecting doesn't quite work either, since, for example, in concrete types ModuleKind.None & number doesn't simplify back to ModuleKind.None.
Replacing the constraint via an infer and then intersecting the original T with the inference kinda works.
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
Activity
[-]Constraints applied by conditional types not considered when checking signatures[/-][+]Constraints applied by conditional types not considered later in control flow[/+][-]Constraints applied by conditional types not considered later in control flow[/-][+]Constraints applied by conditional types not considered when checking signatures[/+]ahejlsberg commentedon Mar 6, 2018
This is actually working as intended. The constraint added to
Tby theT extends stringcheck is in effect only in the true branch of the conditional type. TheTproduced byEqString<T>is exactly the sameTas was passed in and it doesn't have any new constraints. To get the desired effect you need to return an intersection type:weswigham commentedon Mar 6, 2018
Hm. OK. That's not the greatest in the context of using conditionals for control flow narrowing, since it causes you to get intersections instead of constrained generics like you'd expect.
kpdonn commentedon Mar 7, 2018
Wesley Wigham (@weswigham) You very well might already know this, but another way to get your example to work without the intersection is
weswigham commentedon Mar 7, 2018
It's a little verbose but it seems like it checks out.
weswigham commentedon Mar 9, 2018
Erm, doesn't check out too well, in heavy use practice. It may give the result a new constraint on whatever you say, but it forgets its relationship with the original
T, which is bad:weswigham commentedon Mar 9, 2018
sigh just intersecting doesn't quite work either, since, for example, in concrete types
ModuleKind.None & numberdoesn't simplify back toModuleKind.None.Replacing the constraint via an
inferand then intersecting the originalTwith the inference kinda works.typescript-bot commentedon Mar 23, 2018
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.