Skip to content

Conditional type inference gives conflicting results for functions returning booleans #36683

Closed
@vitoke

Description

@vitoke

TypeScript Version: 3.8.0-dev.20200206

Search Terms:
conditional boolean

Code

type Example1<T> = () => T;
type Example2<T> = T extends any ? () => T : never;
type Example3<T> = T extends never ? never : () => T;

function test1<T>(e: Example1<T>): void {}
function test2<T>(e: Example2<T>): void {}
function test3<T>(e: Example3<T>): void {}

test1(() => 1); // ok
test2(() => 1); // ok
test3(() => 1); // ok

test1(() => ''); // ok
test2(() => ''); // ok
test3(() => ''); // ok

test1(() => true); // ok
test2(() => true); // fail
test3(() => true); // fail

test3(() => false);         // fail
test3(() => true as true);  // ok

// root cause: with boolean, conditional type is inferred to be:
type FalseOrTrueReturn = (() => false) | (() => true)
const falseOrTrueReturn: FalseOrTrueReturn = () => (false as boolean)  // fail

// it only fails for function return type, so this works:
type FalseOrTrueArg = ((value: false) => void) | ((value: true) => void)
const falseOrTrueArg: FalseOrTrueArg = (value: boolean) => {} // ok

Expected behavior:
All failing lines should compile just fine. This is a simplified example, but it prevents correct type inference for more complex real-world use-cases.

Actual behavior:
Compiler fails to compile the lines with a function returning a boolean. This is due to the boolean return value being destructured into () => true | () => false, and () => boolean is not assignable to that.

Playground Link:
TS Playground

Related Issues:
Possibly:
#33369
#35861

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions