Reputation: 101
I get the error when compiling a file with typescript:
Property 'qaz' does not exist on type '{ bar: string; }'.
With the following code in the file:
let foo = {
bar: "Can you perform a Quirkafleeg?"
}
let { qaz = "I'm feeling manic!" } = foo;
console.log(qaz);
console.log(qaz.bar);
Based on example code on the page: https://zellwk.com/blog/es6/ in the section "Destructuring objects".
I was expecting to get the second string as output, but I'm a bit confused as there is another example on that page along the lines of:
let { fizz: faz = "Eugene was my friend." } = foo; // as defined above
console.log(fizz);
console.log(fizz.faz);
Which gives a similar error:
Property 'fizz' does not exist on type '{ bar: string; }'.
Upvotes: 9
Views: 18980
Reputation: 249656
The article is about ES destructuring, which is also implemented in typescript. Typescript will however perform extra checks. One of those checks is that you can't destructure from a type that does not declare the property.
So, this will be an error:
let foo = {
bar: "Can you perform a Quirkafleeg?"
}
let { qaz = "I'm feeling manic!" } = foo; //err
While this will work:
let foo = {
bar: "Can you perform a Quirkafleeg?",
qaz: undefined
}
let { qaz = "I'm feeling manic!" } = foo; //ok qaz is "I'm feeling manic!" because of the default
Or you can specify the type explicitly:
let foo: { bar: string, qaz?: string} = {
bar: "Can you perform a Quirkafleeg?",
}
let { qaz = "I'm feeling manic!" } = foo; //ok qaz is "I'm feeling manic!" because of the default
The other part is you can destructure a property to a variable of a different name, so below, we take bar
from foo
and put in fizz
let foo = {
bar: "Can you perform a Quirkafleeg?",
qaz: undefined
}
let { fizz: bar = "Eugene was my friend." } = foo; // basically same as let fizz = foo.bar || "Eugene was my friend."
console.log(fizz); // "Can you perform a Quirkafleeg?"
But the same typescript restriction applies, that bar
in this case must be defined on foo
.
This is generally the extra layer of type checking typescript does, you can't access properties typescript does not know about, either through destructuring or direct access with .
or []
The last part, accessing console.log(fizz.faz);
will never be valid, fizz
is not the original object, it is the string that was in foo.bar
, so it will not have a property faz
or bar
. I believe this is a misunderstand of the source blog on your part, I did not find any such claim in the blog.
Upvotes: 4
Reputation: 37594
That is working as expected. You are destructing and providing a default parameter to qaz
. It should work, but it seems like the tscompiler has an issue with that. You can fix it by providing the type any
e.g.
let foo = { bar: "Can you perform a Quirkafleeg?" }
let { qaz = "I'm feeling manic!" }: any = foo;
console.log(qaz); // I'm feeling manic!
console.log(qaz.bar); // undefined
Upvotes: 2
Reputation: 1216
That's not how Destructuring objects work.
Essentially it will look at the child properties of foo
and assign new variable to them
That must match the property names of
foo
For instance
const Zell = {
firstName: 'Zell',
lastName: 'Liew'
}
let { firstName, lastName } = Zell
console.log(firstName) // Zell
console.log(lastName) // Liew
to fix your example you'll need to do
let foo = {
bar: "Can you perform a Quirkafleeg?"
}
let { bar } = foo;
console.log(bar);
When you try to access 'qaz' on bar it cannot since bar
is a String
EDIT:
To expand in your example
let { qaz = "I'm feeling manic!" } = foo;
When you're assigning qaz
a value via =
it is actually just a default value if it is not found on the object foo.
In your example
let { fizz: faz = "Eugene was my friend." } = foo;
you're trying to assign fizz
to the value of foo.faz
and if fizz
does not exist on foo
it will default to "Eugene was my friend."
Upvotes: 1