Skip to content

Inconsistent inferred overloads in conditional types for no-arg signatures with strictFunctionTypes #28867

@jcalz

Description

@jcalz

TypeScript Version: 3.3.0-dev.20181205

Search Terms:
conditional type, infer, overload, no-arg, zero arguments, strictFunctionTypes

Note that this issue is not about the behavior where the last overload is examined in conditional type inference of a single signature, where some might expect a union or an argument-based choice.

Code

// turn on --strictFunctionTypes

type InferTwoOverloads<F extends Function> = 
  F extends { (...a1: infer A1): infer R1, (...a0: infer A0): infer R0 } ? 
  [(...a1: A1) => R1, (...a0: A0) => R0] : 
  never;

type Expected = InferTwoOverloads<((x: string) => number) & (() => string)>
// [(x: string) => number, () => string]    

type JustOneSignature = InferTwoOverloads<((x: string) => number)>;
// never

type JustTheOtherSignature = InferTwoOverloads<(() => string)>;
// [(...a1: unknown[]) => {}, () => string]

Expected behavior:
I would expect that either both JustOneSignature and JustTheOtherSignature would be never, or both JustOneSignature and JustTheOtherSignature would evaluate to a two-tuple where the first signature is... something. I suppose (...a1: unknown[])=>{}? Or maybe it should be a copy of one of the other overloads? Or something in between?

Actual behavior:
It looks a zero-argument function is being treated pathologically during conditional type inference; if a type is callable with zero arguments, it will be considered assignable to any number of overloads with what looks like failed inference for the types of the arguments (unknown[]) and the return ({}). Otherwise, if a type is only callable with at least one argument, it will only be considered assignable to the matching number of overloads.

This distinction only seems to happen with --strictFunctionTypes on. If you turn it off, JustOneSignature above becomes [(...a1: unknown[]) => {}, (x: string) => number], which is at least consistent with the zero-argument situation.

Playground Link:
🔗

Related Issues:

Metadata

Metadata

Assignees

Labels

Domain: Conditional TypesThe issue relates to conditional typesFix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions