Skip to content

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

Closed
@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

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions