Krishnan Ravikumar
Krishnan Ravikumar

Reputation: 295

Object Destructure in TS with and without explicit variable

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

Answers (1)

Oblosys
Oblosys

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

Related Questions