Skip to content

Type-inference change in 3.6 related to parameter-destructuring with defaults #33474

@aslatter

Description

@aslatter

TypeScript Version: 3.6.3

Search Terms: Type parameter default destructure destructuring

Code

function main() {
    test1([["foo"]]);
    test2([["foo","bar"]])
}

function test1(
	[[d1 = "d1"] = []] = [], // Inferred type of parameter: [([] | undefined)?], was [([(string | undefined)?] | undefined)?] in 3.5
) {
	d1;
}

function test2(
    [[e1 = "e1", e2 = "e2"] = []] = [], // inferred type of parameter: [([] | undefined)?], was [([(string | undefined)?, (string | undefined)?] | undefined)?] in 3.5
) {
    e1;
    e2;
}

Expected behavior:

In TypeScript 3.5 (and some prior versions) the above program type-checked.

Actual behavior:

As of (at least) TypeScript 3.6.3 I get two type-check errors:

For the call to test1:

Argument of type '[[string]]' is not assignable to parameter of type '[([] | undefined)?]'.
  Types of property '0' are incompatible.
    Type '[string]' is not assignable to type '[]'.
      Types of property 'length' are incompatible.
        Type '1' is not assignable to type '0'.ts(2345)

For the call to test2:

Argument of type '[[string, string]]' is not assignable to parameter of type '[([] | undefined)?]'.ts(2345)

We don't have production code like this, but we do have some of it in our test-suite.

It's not a big deal for us to accommodate the change, but I thought I'd submit an issue in case the change in behavior has broader impact.

The inferred types look wrong for these cases - previously we inferred from the default that the inner-inner array-member was allowed to be a string, now we infer that the inner-array must be empty.

This bug only affects defaulting with nested arrays - using a single array with defaulting doesn't have this problem:

// this works as expected
function test3(
	[f1 = "f1"] = [], // parameter has the inferred type:  [(string | undefined)?]
) {
	f1;
}

Here, we correctly default the type of the parameter to test3 to be [(string | undefined)?].

Giving an explicit type to the parameters to test1 and test2 make the call work fine.

Playground Link: http://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAWwIYzACgJSIN4BQixiUApgM5QCMmA2nQETBxyMC672A3ESeVQBM9JizYAaRgCNUAJw5cCAXwIFQkWAlKUamAgEgGAE2qIAvIkYmO5xHU6374grkL6TvFWvDR4SAVDCfMQMZKYWjGGM4ohkgraRgjYW9uyO7M6uwbHUvCSxgp5AA

Related Issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions