Reputation: 295
In TS, This code compiles successfully...
let amir = {email: '[email protected]', admin: true}
function sendEmail({email}: {email: string}): string {
return `Emailing ${email}`
}
sendEmail(amir)
However, this code,
function extractEmail({email}: {email: string}): string {
return `Emailing ${email}`
}
extractEmail({email: '[email protected]', user: 'admin'})
throws error:
Argument of type '{ email: string; user: string; }' is not assignable to parameter of type '{ email: string; }'.
Object literal may only specify known properties, and 'user' does not exist in type '{ email: string; }'.(2345)
How does explicity declaring the object in a let makes the code different?
Upvotes: 2
Views: 113
Reputation: 15106
As mentioned by @Countingstuff, the TypeScript Handbook explains the reasoning, but it fails to mention a key point: if you pass a literal object with excess properties to a function, there is no way to access those properties anywhere, so it makes sense to flag them as errors. If the code below would be valid, the x
property would always be pointless:
f({a: 1, x: true})
function f(a: {a: number}) {
console.log(a.x) // cannot access `x` here
}
// cannot access `x` here either
The same thing happens when assigning a literal object to a variable or a constant with a narrower type:
const a: {a: number} = {a: 1, x: true}
console.log(a.x) // cannot access `x`
However, if you first assign the literal to a variable or constant, it is no longer necessarily an error:
const o = {a: 1, x: true}
function f(a: {a: number}) {
console.log(a.x) // still cannot access `x` here
}
console.log(o.x) // but here we can
And similarly for an assignment to a narrower type:
const o = {a: 1, x: true}
const a: {a: number} = o
console.log(o.x)
Upvotes: 1