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'.
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
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
nameandageare not present in{}, so ifparams === undefined, thennameandagewill be undefined. You can get around this by adding a type annotation like soconst { name, age }: Person = params || {}.