Define attributes directly in constructors

In Typescript, properties can be defined directly as arguments to constructors. Let’s start with an early example:

class Note {
  public title: string;
  public content: string;
  private history: string[];
  
  constructor(title: string, content: string, history: string[]) {
    this.title = title;
    this.content = content;
    this.history = history; }}Copy the code

Use the ts shorthand syntax:

class Note {
  constructor(public title: string, public content: string, private history: string[]){
    // this. Title = title}}Copy the code

It may not look like a class with attributes, but it does, using the Typescript shorthand for defining attributes directly with constructor arguments.

This shorthand syntax does a lot:

  • Declares a constructor parameter and its type
  • Declares a public property with the same name
  • When we new an instance of the class, we initialize the property to the corresponding parameter value

A null value merge

Coalescing Nullish Coalescing That sounds a little confusing, so let’s go straight to the code

const i = undefined
const k = i ?? 5
console.log(k) / / 5

/ / 3.9.2 compilation
const i = undefined;
constk = i ! = =null&& i ! = =void 0 ? i : 5;
console.log(k); / / 5
Copy the code

At this point you must want to say that’s the end of it, right?

let k = i || 5
Copy the code

It works, but don’t you think it’s a little loose? What if I is equal to 0?

Private class field

TypeScript 3.8 will support ECMAScript private fields, not to be confused with TypeScript private modifiers.

This is a class with private class fields in TypeScript:

class Animal {
  #name: string;
  constructor(theName: string) {
    this.#name = theName; }}Copy the code

The difference between using a private class field over the private keyword is that it has better runtime guarantees. TypeScript fields declared with the private keyword become normal fields in compiled JavaScript code. Private class fields, on the other hand, remain private in compiled code.

Attempting to access a private class field at run time results in a syntax error. We can’t check the private class fields using browser development tools.

With private class fields, we finally have real privacy in JavaScript.

Labeled tuple Types

Named tuple types are available only in TypeScript 4.0 or later, and can greatly improve our development experience and productivity. Here’s an example:

type Address = [string, number]

function setAddress(. args: Address) {
  // some code here
  console.log(args)
}
Copy the code

When we define a function’s entry parameters in this way, the editor’s intelligent prompt only tells us the type of the parameter when using the function, losing the description of the parameter’s meaning.

To improve this, we can do Labeled tuple types. We can define parameters like this:

type Address = [streetName: string, streetNumber: number]

function setAddress(. args: Address) {
  // some code here
  console.log(args)
}
Copy the code

This way, when we call the function, our parameters get semantics, which makes the code much easier to maintain.

Template literal types

Since ES6, we have been able to write strings in backquotes, not just single or double quotes, through the feature of Template Literals:

const message = `text`;
Copy the code

As Flavio Copes notes, template literals provide features that previously were not available in quotation marks:

  • Defining multi-line strings is handy
  • Interpolation of variables and expressions can be done easily
  • You can create DSLS (Domain Specific Languages) with template tags

Template literals have the same syntax as template strings in JavaScript, except that they are used in type definitions:

type topBottom = "top" | "bottom"
type leftRight = "left" | "right"

type Position = `${topBottom }-${leftRight }`
Copy the code

When we define a specific literal type, TypeScript produces a new string literal type by concatenating the content.

A practical type

TypeScript gives you a set of utility types that allow you to build new types out of existing ones. There are many utility types that cover different situations, such as selecting type attributes to copy, uppercase letters, or making all attributes optional.

Here is an example of using the Omit tool, which copies all attributes of the original type except those we have chosen not to include.

type User = {
  name: string
  age: number
  location: string
}

type MyUser = Omit<User, 'name'>
Copy the code