TypeScript learning notes: type narrowing

TypeScript learning notes: type narrowing

Preface

The best thing about TS is strong typing, which is followed by type narrowing. I will summarize it while I am at it.

Type Inference

In TypeScript, type inference helps provide types where there are no explicit types.

Example:

let x = [0, 1, null] // number

let x = Math.random() < 0.5 ? 100 : "helloword" // number|string

let x: Animal[] = [new Rhino(), new Elephant(), new Snake()]; // Rhino | Elephant | Snake

If no best common type is found, the result of type inference is a union array type.

Union Types and Type Guards

Example:

// Union type type Types = number | string

function typeFn(type: Types, input: string): string {
  // If you write this, you need to determine the type of type}

Can directly assign type inference

let x:number|string = 1
x="tiedan"

If you don't judge, you will get an error.

function typeFn(type: number | string, input: string) {
  // Error operator + cannot be applied to string 
  return new Array(type + 1).join("") + input
}

So we have to judge

function typeFn(type: number | string, input: string) {
  // Type guard if (typeof type === 'number') {
    return new Array(type + 1).join(" ") + input
  }
  return type + input
}

Type narrowing is to redefine a more specific type based on the judgment type

So the question is, why learn this? Isn't js good?

Personal opinion:

Using TypeScript can help you reduce the vulnerability of JavaScript as a weak language, and reduce the risk of errors caused by incorrect types and the risk of errors caused by mixing various JavaScript versions.

TypeScript simply introduces the most important feature of strong typing of high-level languages ​​into JavaScript, which solves the problem of preventing unexpected errors caused by data type conversion when writing JavaScript code, which increases the difficulty of troubleshooting.

Type guards for typeof:

"string"
"number"
"bigint" // ES10 adds "boolean"
"symbol" // ES6 adds "undefined"
"object"
"function"

Note: typeof null is equal to object

therefore:

function strOrName(str: string | string[] | null) {
  if (typeof str === 'object') {
    for (const s of str) {
      // Report an error because str may be null
      console.log(s)
    }
  } else if (typeof str === 'string') {
    console.log(str)
  } else {
    //......
  }
}

Truth value narrowing

The truth table of js is very complicated. Except for the following, which is false, all others are true.

0
NAN
""
0n // Bigint version of 0 null
undefined

To avoid null errors, you can use truth value narrowing

// Use true value to judge if (str && typeof strs === 'object') {
  for (const s of strs) {
    console.log(s)
  }
}

Or this is also OK

function valOrName(values: number[] | undefined, filter: number): number[] | undefined {
  if (!values) {
    return values
  } else {
    return values.filter(x => x > filter)
  }
}

Summary: Truth value narrowing helps us better handle null/undefined/0 and other values

Narrowing of equality

If you want to narrow the equality, you can use operators such as ===, !==, ==, and, and != to narrow the equality.

Example 1:

function strOrNum(x: string | number, y: string | boolean) {
  if (x === y) {
    // string
  } else {
    // string|number
  }
}

Example 2:

function strOrName(str: string | string[] | null) {
  if (str !== null) {
    if (typeof str === 'object') {
      for (const s of str) {
        console.log(s) // []
      }
    } else if (typeof str === 'string') {
      console.log(str) // string
    } else {
      // .....
    }
  }
}

Example3:

interface Types {
  value: number | null | undefined
}

function valOrType(type: Types, val: number) {
  // null and undefined are both false and can only be numbers
  if (type.value != null) {
    type.value *= val
  }
}

in operator narrowing

in checks whether there is a property in the object, and now acts as a "type guard".

Example:

interface A { a: number };
interface B { b: string };

function foo(x: A | B) {
    if ("a" in x) {
        return xa;
    }
    return xb;
}

Narrowing instanceof

The right-hand side of an instanceof expression must be of type any, or of a type assignable to the Function interface type.

Example:

function dateInval(x: Date | string) {
  if (x instanceof Date) {
    // Date
  } else {
    // string
  }
}

The nature of narrowing

The essence of narrowing is to redefine the type

Example:

function example() {
  let x: string | number | boolean
  x = Math.random() < 0.5
  if (Math.random() < 0.5) {
    x = 'hello' // string
  } else {
    x = 100 // number
  }
  return x; // string|number
}

Narrowing of Union Types

Example 1:

interface Shape {
  kind: "cirle" | "square",
  redius?: number
  sideLength?: number
}

// Error function getArea(shape: Shape) {
	return Math.PI * shape.redius ** 2
}
// Narrowing or error function getArea(shape: Shape) {
  if (shape.kind === 'cirle') {
    return Math.PI * shape.redius ** 2
  }
}
// Using non-null assertion function getArea(shape: Shape) {
  if (shape.kind === 'cirle') {
    return Math.PI * shape.redius! ** 2
  }
}

Example 2:

interface Circle {
  kind: "cirle";
  redius: number;
}

interface Square {
  kind: "square";
  redius: number;
}

type Shape = Circle | Square

function getArea(shape: Shape) {
  if (shape.kind === 'cirle') { // narrow return Math.PI * shape.redius ** 2
  }
}

// or function getArea(shape: Shape) {
  switch (shape.kind) {
    case "cirle":
      return Math.PI * shape.redius ** 2
    case "square":
      return shape.sideLength ** 2
    default:
      const _example: never = shape
      return _example
  }
}

Summarize

This is the end of this article about TypeScript learning notes on type narrowing. For more relevant TypeScript type narrowing content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • TypeScript Type Innference
  • TypeScript Basic Data Types
  • TypeScript Advanced Types You Don’t Know (Summary)
  • TypeScript learning notes: basic types

<<:  How to modify the master-slave replication options in MySQL online

>>:  Ubuntu 16.04 kernel upgrade steps

Recommend

Detailed examples of converting rows to columns and columns to rows in MySQL

mysql row to column, column to row The sentence i...

The latest MySQL 5.7.23 installation and configuration graphic tutorial

The detailed installation and configuration of th...

Detailed explanation of JavaScript's built-in Date object

Table of contents Date Object Creating a Date Obj...

Summary of CSS counter and content

The content property was introduced as early as C...

Vue3 Vue Event Handling Guide

Table of contents 1. Basic event handling 2. Send...

How to call the browser sharing function in Vue

Preface Vue (pronounced /vjuː/, similar to view) ...

What are the image file formats and how to choose

1. Which three formats? They are: gif, jpg, and pn...

MySQL installation tutorial under Windows with pictures and text

MySQL installation instructions MySQL is a relati...

Vue3.0 implements the magnifying glass effect case study

The effect to be achieved is: fixed zoom in twice...

Summary of the use of element's form elements

There are many form elements. Here is a brief sum...

MYSQL performance analyzer EXPLAIN usage example analysis

This article uses an example to illustrate the us...