@TOC

When can type assertions be made?

  • For class A to be asserted as class B, either A is compatible with B or B is compatible with A
  • A union type can be asserted as one of these types
  • A parent class can be asserted as a child class or a child class can be asserted as a parent class
  • The any type can be asserted to any type

For example,

When we want to call swim and are not sure of the type, we assert the type to Fish and no error will be reported

interface Cat {
  name: string;
  run(): void;
}
interface Fish {
  name: string;
  swim(): void;
}
function swim(animal: Cat|Fish){
  // return animal.swim() // error TS2339: Property 'swim' does not exist on type 'Cat | Fish'
  return (animal as Fish).swim()
}
const Hanly: Fish = {
  name: 'Tom',
  swim(): void{
    console.log('That Hanly fish is swimming')
  }
}
swim(Hanly)
Copy the code

Note that type assertions can only “fool” the TypeScript compiler and cannot avoid runtime error causes: The return value of Swim is asserted to be of type Fish. The Typescript compiler trusts this assertion, so swim does not get an error, but Cat does not have a swim method

const Tom: Cat = {
  name: 'Tom',
  run(): void{
    console.log('That Tom cat is running')
  }
}
swim(Tom); // There is no error when compiling
Copy the code

Assert the parent class as a more concrete subclass

class ApiError extends Error{
  code:number = 1;
}
class OtherError extends Error{
  statusCode:number = 2;
}

function isApi(error: Error) :boolean{
  // error.code = 2; // The parent class Error has no code attribute, so getting Error. Code directly is an Error
  if(typeof (error as ApiError).code === 'number') {return true
  }else{
    return false}}Copy the code

A subclass is asserted to be the parent class

class Person {
  name:string;
  age:number;
}
class Teacher extends Person {
  eat():void{
    console.log('At dinner')}}const tt = new Teacher();
(tt as Person).name = 'tony';
Copy the code

One thing to note

An error is reported when we refer to a property or method that does not exist on this type

function fn(val: string | number) :number {
  if ((val as string).length) {
    return (val as string).length
  } else {
    return val.toString().length
  }
}
fn(1)
fn("1")
Copy the code

Adding foo to window will cause a compilation error because there is no foo under window

window.foo = 1; // Compile error
// Type assertion is required to temporarily assert the window to type any
 (window as any).foo = 1
Copy the code

Double assertion

That is to break the rule that for class A to be asserted as class B, only A needs to be compatible with B or B needs to be compatible with A, so that any type can be asserted as any other type. If you use this double assertion, it’s probably very wrong, and it’s likely to result in a runtime error. Never use double assertion unless you absolutely have to

class A {
  name: string = 'zy';
}
class B {
  age: number = 18;
}
function assertAny(a: A) :void {
  const age = (a as any as B).age;
  console.log(age)
}
assertAny({ name: 'tony' })
Copy the code

Thank you for reading.