question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Conditional type doesn't narrow primitive types

See original GitHub issue

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>

Playground Link: https://www.typescriptlang.org/play/#src=type OnlyNumber<T extends number> %3D T type ToNumber<T extends number | string> %3D T extends string %3F undefined %3A OnlyNumber<T>

Related Issues:

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:10
  • Comments:7 (6 by maintainers)

github_iconTop GitHub Comments

6reactions
weswighamcommented, Aug 7, 2018

This is just a manifestation of how we don’t track negated constraints in the false branch of a conditional type.

0reactions
flushentitypacketcommented, 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.

type OptionalFn = (() => string) | undefined
// Type 'OptionalFn' does not satisfy the constraint '(...args: any[]) => any'.
// Type 'undefined' is not assignable to type '(...args: any[]) => any'
type OptionalFnReturnType = OptionalFn extends undefined ? undefined : ReturnType<OptionalFn>

Can workaround by manually narrowing type:

type OptionalFn = (() => string) | undefined
type OptionalFnReturnType = OptionalFn extends undefined ? undefined : ReturnType<NonNullable<OptionalFn>>

(See NonNullable source in the Typescript docs)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Conditional types don't narrow properly - Stack Overflow
The type of cb is still unknown after if(cb); return res cannot match the right type, i.e. Promise<Result[]>. How ...
Read more >
Documentation - Conditional Types - TypeScript
Often, the checks in a conditional type will provide us with some new information. Just like with narrowing with type guards can give...
Read more >
6 ways to narrow types in TypeScript | Building SPAs
Doing a truthly condition check will remove null and undefined from a type. A typeof type guard is a great way to narrow...
Read more >
The guide to conditional types in TypeScript - LogRocket Blog
Conditional types let us deterministically define type transformations depending on a condition. In brief, they are a ternary conditional ...
Read more >
The Power and Limitations of Conditional Types and the “infer ...
TypeScript opens this up to us through conditional types. They provide a way for us to make logical decisions at the type level....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found