Skip to content

TS 4.0 Variadic tuple types: type inference with optional element not working as expected #39253

@bela53

Description

@bela53

TypeScript Version: 4.0.0-dev.20200624 (Nightly)

Search Terms: variadic tuple optional element type inference

Code

type Foo<T extends string[]> = [...T, number?]

// These are the expected types
const v11: Foo<[]> = [] // [(number | undefined)?]
const v12: Foo<["bar"]> = ["bar"] // ["bar", (number | undefined)?]
const v13: Foo<["bar"]> = ["bar", 42] // ["bar", (number | undefined)?]

// inferring types with helper function produces different results
function foo<T extends string[]>(t: [...T, number?]): [...T, number?] { return t }
const v21 = foo([]) // (string | number | undefined)[]  //❓
const v22 = foo(["bar"]) // [(number | undefined)?]   // error,❓
const v23 = foo(["bar", 42]) // ["bar", (number | undefined)?] // ✅

Expected behavior:
The inferred types via foo helper function (v21 etc.) are the same as explicitly annotated types (v11 etc.).

I would expect the passed in array literal value in foo to be narrowed to a tuple type, as explained in the PR:

When the contextual type of an array literal is a tuple type, a tuple type is inferred for the array literal. The type [...T], where T is an array-like type parameter, can conveniently be used to indicate a preference for inference of tuple types

Actual behavior:
Either the resulting type is an array (v21) or does not take the variadic type into account (v22), despite explicit [...T, number?] return type for foo. Also v22 errors now.

I could live with v21, but shouldn't it be clear to the compiler in v22, that the resulting type is akin to ["bar", undefined?]?

Playground Link:
here

Related Issues:

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions