typescripttypeguards

Assert is typeguard


Can anybody explain to me why in the console log the notUser has a type

const notUser: {
    items: any[];
} & User

I expect it to be User

interface User {
  id: string
}
function assVal (obj:any): asserts obj is User {
  if(!('id' in obj && typeof obj.id === 'string')) throw new Error()
}

const notUser = {items: []}

assVal(notUser)

console.log(notUser)

as same as in this example:

interface User {
  id: string
}
function isUser (obj:any): obj is User {
  return 'id' in obj && typeof obj.id === 'string'
}

const notUser = {items: []}

if(isUser(notUser)) {
  console.log(notUser)
}

In if block the notUser has a type

const notUser: {
    items: any[];
} & User

Solution

  • The variable const notUser is declared inferred to have the type { items: any[]; } due to its declaration. That means it could hold any object that has at least has an .items array property. It may also have other properties, like an .id string, TypeScript doesn't know or care here, those would still be compatible.

    The type guard narrows the type of the variable, since it is (in the guarded scope) also known to be a User. But that doesn't mean it looses its original type, rather, it has both.