Typescript: Type inferring doesn't work in destructuring.

Created on 7 Sep 2017  ·  4Comments  ·  Source: microsoft/TypeScript

TypeScript Version: 2.4.2
Tested in VS Code. The online playground seems broken.

Code

interface Person {
  name?: string,
  age?: number
}

const defaultPerson: Person = {
  name: 'Bob',
  age: 19,
}

const girl: Person = {
  name: 'Alice',
  age: 23,
}

// [ts] Initializer provides no value for this binding element and the binding element has no default value.
const { name, age } = {...defaultPerson, ...girl}

Expected behavior:

The const 'name' and 'age' are inferred as 'sting' and 'number'

Actual behavior:
TS report: [ts] Initializer provides no value for this binding element and the binding element has no default value.

The workarounds:

// A
const p = {...defaultPerson, ...girl}
const { name, age } = p

// B
const { name, age } = {...defaultPerson, ...girl} as Person

// C
const { name = 'Tom', age = 19 } = girl

Although we have workarounds, I can't understand why we can't get types directly in destructuring. Compare to solution A, TS definitely can infer the types of 'p'.

Bug Fixed

Most helpful comment

@brunolemos can you open a separate issue or search for another existing issue? This bug has to do with a spread that is contextually typed by a binding pattern. Your example doesn't have a spread in it.

Based on your one-line example, it looks like you get an error because Typescript notices that name and age are not present in {}, so if params === undefined, then name and age will be undefined. You can get around this by adding a type annotation like so const { name, age }: Person = params || {}.

All 4 comments

Fix is up at #18925

I still have this error when I add || {}:
const { name, age } = params || {}

@brunolemos can you open a separate issue or search for another existing issue? This bug has to do with a spread that is contextually typed by a binding pattern. Your example doesn't have a spread in it.

Based on your one-line example, it looks like you get an error because Typescript notices that name and age are not present in {}, so if params === undefined, then name and age will be undefined. You can get around this by adding a type annotation like so const { name, age }: Person = params || {}.

@sandersn if that works it's fine then, thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

siddjain picture siddjain  ·  3Comments

fwanicka picture fwanicka  ·  3Comments

seanzer picture seanzer  ·  3Comments

Antony-Jones picture Antony-Jones  ·  3Comments

jbondc picture jbondc  ·  3Comments