[secure TypeScript] union type, cross type and type protection

Hello, I'm A bowl week , a front end that doesn't want to be drunk. If you are lucky enough to get your favor, I am very lucky~

Union type

The so-called joint type is to define some types. The defined variables only need to meet any type. The joint type is defined by | and the example code is as follows:

// Union types are defined by the | symbol
let value: number | boolean | string = 'A bowl week'
value = 18

In the above code, we define a value variable, which can be of type number, boolean or string.

Cross type

Introduces the union type, and then introduces the cross type that is particularly similar to it.

The so-called cross type is to meet all types, and the cross type is defined by & symbol. The ex amp le code is as follows:

// Define three common interface types
interface Name {
  name: string
}
interface Age {
  age: number
}
interface Hobby {
  hobby: string
}
// Define an object that is the union type of the above three objects
let person: Name & Age & Hobby = {
  // If less than one type is allocated, an exception will be thrown
  name: 'A bowl week',
  age: 18,
  hobby: 'coding',
}

Type protection

Now we have a requirement: get the first number in an array of any type.

The implementation code is as follows:

// Define an array containing number or string
const arr: (number | string)[] = [1, 'number']
// Traversing the array returns the first number
const getValue: (arr: (number | string)[]) => number = (
  arr: (number | string)[],
): number => {
  for (let i = 0; i < arr.length; i++) {
    // Returns if the current value is not a NaN when converted to a number
    if (!isNaN(Number(arr[i]))) {
      return arr[i] // Type 'string | number' cannot be assigned to type 'number'.
    }
  }
}

When returning in the above code, you do not know whether the returned is a number type. So an exception will be thrown.

The above functions can be completed through type assertion. The example code is as follows:

const getValue: (arr: (number | string)[]) => number = (
  arr: (number | string)[],
): number => {
  for (let i = 0; i < arr.length; i++) {
    // Returns if the current value is not a NaN when converted to a number
    if (!isNaN(Number(arr[i]))) {
      return arr[i] as number // Tell the compiler that I return a number
    }
  }
}

What are type assertions? Refer to: Type Asserts

If you use type assertion to explain, it will be cumbersome if the data types you want are different. At this time, type protection is required to complete this function. Type protection is mainly divided into the following three types:

Custom type protection

The method of user-defined type protection is to define a function whose return structure is in the form of parameterName is type, which is a type predicate. parameterName must be a parameter name from the current function parameter. The example code is as follows:

// Use custom type protection
// 1. Define a function whose return value is a type predicate, that is, parameterName is Type, that is, the form of parameter name is type
function isNumber(value: number | string): value is number {
  // If true is returned, the value passed in is the type after is
  return !isNaN(Number(value))
}
// 2. Define a function to get numbers
const getNumber: (value: number | string) => number = (
  value: number | string,
): number => {
  // If the value of calling isNumber is true, it means that value is a number, so the number is returned
  if (isNumber(value)) {
    return value
  }
}
// 3. Call to get the final value
const getValue: (arr: (number | string)[]) => number = (
  arr: (number | string)[],
): number => {
  for (let i = 0; i < arr.length; i++) {
    // If a number is returned, it is converted to boolean and the value is true
    if (getNumber(arr[i]) || getNumber(arr[i]) === 0) {
      return getNumber(arr[i])
    }
  }
}

The reason for defining the second function is that there is still a problem with directly using i as the return value in the array, so define a function transition.

typeof type protection

The typeof keyword in JavaScript can judge the current type, but only number, string, boolean and symbol can be judged.

That's enough in this requirement. Next, let's see how to implement type protection through typeof. The example code is as follows:

// 1. Define a function to get numbers
const getNumber: (value: number | string) => number = (
  value: number | string,
): number => {
  // Judge whether the current is a string. If yes, return the current value
  if (typeof value === 'number') {
    return value
  }
}
// 2. Call to get the final value
const getValue: (arr: (number | string)[]) => number = (
  arr: (number | string)[],
): number => {
  for (let i = 0; i < arr.length; i++) {
    // If a number is returned, it is converted to boolean and the value is true
    if (getNumber(arr[i]) || getNumber(arr[i]) === 0) {
      return getNumber(arr[i])
    }
  }
}

instanceof type protection

The instanceof operator is also a native operator provided in JavaScript. It is used to determine whether an instance is created by a constructor or a class using ES6 syntax. In TypeScript, you can also implement type protection through the instanceof operator. The example code is as follows:

/**
 * Since instanceof only supports reference types and does not support original types, it needs to be changed here to modify the array as follows:
 */
const arr2: (Number | String)[] = [new String('Prosperity on the other side'), new Number(10)]
// 1. Define a function to get numbers
const getNumber: (value) => number = (value): number => {
  // Judge whether the current value is of type Number, convert the current value into a string and return
  if (value instanceof Number) {
    return Number(value)
  }
}
// 2. Call to get the final value
const getValue: (arr: (Number | String)[]) => number = (
  arr: (Number | String)[],
): number => {
  for (let i = 0; i < arr.length; i++) {
    // If a number is returned, it is converted to boolean and the value is true
    if (getNumber(arr[i]) || getNumber(arr[i]) === 0) {
      return getNumber(arr[i])
    }
  }
}

When using instanceof, you should pay attention to the following two points:

  • Only applicable to any reference type, original type is not supported.

  • Whether the prototype chain of the former contains the prototype object of the latter.

Previous recommendation

Keywords: Javascript Front-end TypeScript

Added by cwspen on Thu, 16 Dec 2021 02:25:14 +0200