TypeScript 4.0 Unleashed

Posted by Jayesh Shinde on August 22, 2020 · 4 mins read

Few Months back 3.8 and 3.9 version released which brought type-only imports/exports, along with ECMAScript features like private fields, top-level await in modules, and new export * syntaxes, improving the performance and scalability.

What’s New Summary

What’s New? Lets dive in to feature Which are most important to Developer Point of View.

unknown on catch Clauses

TypeScript 4.0 now lets you specify the type of catch clause variables as unknown instead. unknown is safer than any because it reminds us that we need to perform some sorts of type-checks before operating on our values.

try {
  // ...
} catch (e: unknown) {
  // Can't access values on unknowns
  // error: Object is of type 'unknown'.
  console.log(e.toUpperCase()); 

  if (typeof e === "string") {
    // We've narrowed 'e' down to the type 'string'.
    console.log(e.toUpperCase());
  }
}

Class Properties Inference from Constructors

TypeScript 4.0 can now use control flow analysis to determine the types of properties in classes when noImplicitAny is enabled.

class Square {
  // Previously both of these were any
  area;
// ^ = (property) Square.area: number
  sideLength;
// ^ = (property) Square.sideLength: number
  constructor(sideLength: number) {
    this.sideLength = sideLength;
    this.area = sideLength ** 2;
  }
}

In cases where not all paths of a constructor assign to an instance member, the property is considered to potentially be undefined.

class Square {
  sideLength;
// ^ = (property) Square.sideLength: number | undefined

  constructor(sideLength: number) {
    if (Math.random()) {
      this.sideLength = sideLength;
    }
  }

  get area() {
    return this.sideLength ** 2;
 // error: Object is possibly 'undefined'.
  }
}

In cases where you know better (e.g. you have an initialize method of some sort), you’ll still need an explicit type annotation along with a definite assignment assertion (!) if you’re in strictPropertyInitialization.

class Square {
  // definite assignment assertion
  //        v
  sideLength!: number;
  //         ^^^^^^^^
  // type annotation

  constructor(sideLength: number) {
    this.initialize(sideLength);
  }

  initialize(sideLength: number) {
    this.sideLength = sideLength;
  }

  get area() {
    return this.sideLength ** 2;
  }
}