Conditional type doesn't narrow primitive types #26240
Copy link
Copy link
Open
Labels
In DiscussionNot yet reached consensusNot yet reached consensusSuggestionAn idea for TypeScriptAn idea for TypeScript
Description
TypeScript Version: 3.1.0-dev.201xxxxx
Search Terms:
Code
type OnlyNumber<T extends number> = T
type ToNumber<T extends number | string> =
T extends string ? undefined : OnlyNumber<T>Expected behavior:
No errors
Actual behavior:
Error:
index.ts:37:47 - error TS2344: Type 'T' does not satisfy the constraint 'number'.
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
37 T extends string ? undefined : OnlyNumber<T>
Related Issues:
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
In DiscussionNot yet reached consensusNot yet reached consensusSuggestionAn idea for TypeScriptAn idea for TypeScript
Activity
sergey-shandar commentedon Aug 6, 2018
IMHO, this's issue is slightly related to #26199. It looks like TS doesn't properly handle underlying JavaScript types. I mean, each TS type should have two components:
boolean,number,null,undefined,object,symbol,function}, akaunknown. See also JS typeof.All type computations should be based on these two independent components.
AnyhowStep commentedon Aug 7, 2018
Wouldn't this be perfectly fine if you just did
extends number ? OnlyNumber<T> : undefined?falsandtru commentedon Aug 7, 2018
Looks like not limited to primitive types.
AnyhowStep commentedon Aug 7, 2018
What's wrong with this?
sergey-shandar commentedon Aug 7, 2018
AnyhowStep yes, it's workaround for the bug which works fine for the specific sample case.
weswigham commentedon Aug 7, 2018
This is just a manifestation of how we don't track negated constraints in the
falsebranch of a conditional type.flushentitypacket commentedon Feb 14, 2019
I think I've run into the same issue but in a different context--just going to add this here to put a snippet in for anyone searching for answers for the same type of problem.
Can workaround by manually narrowing type:
(See
NonNullablesource in the Typescript docs)