.type protection
- Type protection is some expressions. They can use type information to ensure the type of variables in a certain scope during compilation.
- Type protection is the ability to determine the type in a branch through keywords
1. typeof type protection
ts
function double(input: string | number | boolean) {
if (typeof input === "string") {
return input + input;
} else {
if (typeof input === "number") {
return input * 2;
} else {
return !input;
}
}
}2. instanceof type protection
ts
class Animal {
name!: string;
}
class Bird extends Animal {
swing!: number;
}
function getName(animal: Animal) {
if (animal instanceof Bird) {
console.log(animal.swing);
} else {
console.log(animal.name);
}
}3. null protection
- If the strictNullChecks option is turned on, methods and properties on variables that may be null cannot be called.
ts
function getFirstLetter(s: string | null) {
//第一种方式是加上null判断
if (s == null) {
return "";
}
//第二种处理是增加一个或的处理
s = s || "";
return s.charAt(0);
}
//它并不能处理一些复杂的判断,需要加非空断言操作符
function getFirstLetter2(s: string | null) {
function log() {
console.log(s!.trim());
}
s = s || "";
log();
return s.charAt(0);
}4. chain judgment operator
- The chain judgment operator is an operator that first checks whether a property exists before trying to access the property. Its symbol is ?.
- If the operand ?. on the left side of the operator evaluates to undefined or null, the expression evaluates to undefined .Otherwise, the target property access, method or function call is triggered normally.
ts
a?.b; //如果a是null/undefined,那么返回undefined,否则返回a.b的值.
a == null ? undefined : a.b;
a?.[x]; //如果a是null/undefined,那么返回undefined,否则返回a[x]的值
a == null ? undefined : a[x];
a?.b(); // 如果a是null/undefined,那么返回undefined
a == null ? undefined : a.b(); //如果a.b不函数的话抛类型错误异常,否则计算a.b()的结果
a?.(); //如果a是null/undefined,那么返回undefined
a == null ? undefined : a(); //如果A不是函数会抛出类型错误
//否则 调用a这个函数The chain judgment operator is still in stage 1 and is not supported by TS yet.
5. Recognized union types
- It is a technique to use common fields in union types for type protection.
- Different values of the same field are identifiable
ts
interface WarningButton {
class: "warning";
text1: "修改";
}
interface DangerButton {
class: "danger";
text2: "删除";
}
type Button = WarningButton | DangerButton;
function getButton(button: Button) {
if (button.class == "warning") {
console.log(button.text1);
}
if (button.class == "danger") {
console.log(button.text2);
}
}Type literal + discernible union type
ts
interface User {
username: string;
}
type Action =
| {
type: "add";
payload: User;
}
| {
type: "delete";
payload: number;
};
const UserReducer = (action: Action) => {
switch (action.type) {
case "add":
let user: User = action.payload;
break;
case "delete":
let id: number = action.payload;
break;
default:
break;
}
};6. in operator
- The in operator can be used to determine parameter types
ts
interface Bird {
swing: number;
}
interface Dog {
leg: number;
}
function getNumber(x: Bird | Dog) {
if ("swing" in x) {
return x.swing;
}
return x.leg;
}7. Custom type protection
- Type guards in TypeScript are essentially expressions that check type information at runtime to ensure that the types in a certain scope are as expected.
- type is Type1Class is the type predicate
- The predicate is of the form parameterName is Type. parameterName must be a parameter name from the current function signature.
- Whenever isType1 is called with some variable, TypeScript will narrow the variable to that specific type if the original types are compatible
ts
function isType1(type: Type1Class | Type2Class): type is Type1Class {
return (<Type1Class>type).func1 !== undefined;
}ts
interface Bird {
swing: number;
}
interface Dog {
leg: number;
}
//没有相同字段可以定义一个类型保护函数
function isBird(x: Bird | Dog): x is Bird {
return (<Bird>x).swing == 2;
//return (x as Bird).swing == 2;
}
function getAnimal(x: Bird | Dog) {
if (isBird(x)) {
return x.swing;
}
return x.leg;
}8. unknown
- TypeScript 3.0 introduces a new unknown type, which is the safe type corresponding to the any type
- The main difference between unknown and any is that the unknown type is more strict: before performing most operations on a value of unknown type, we must perform some form of check.And we don't have to do any checks before performing an operation on a value of type any
8.1 any type
- In TypeScript, any type can be classified as any type.This makes the any type the top-level type of the type system (also known as the global supertype).
- TypeScript allows us to perform any operation on a value of type any without performing any form of checking beforehand
ts
let value: any;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = Math.random; // OK
value = null; // OK
value = undefined; // OK
let value: any;
value.foo.bar; // OK
value.trim(); // OK
value(); // OK
new value(); // OK8.2 unknown type
Just as all types can be classified as any, all types can be classified as unknown.This makes unknown another top-level type in the TypeScript type system (the other being any )
Any type can be assigned to an unknown type
ts
let value: unknown;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = Math.random; // OK
value = null; // OK
value = undefined; // OK
value = new TypeError(); // OKThe unknown type can only be assigned to the any type and the unknown type itself
ts
let value: unknown;
let value1: unknown = value; // OK
let value2: any = value; // OK
let value3: boolean = value; // Error
let value4: number = value; // Error
let value5: string = value; // Error
let value6: object = value; // Error
let value7: any[] = value; // Error
let value8: Function = value; // Error8.3 Narrow the range of unknown types
- Without type assertion or type refinement, no operation can be performed on unknown
- typeof
- instanceof
- Custom type protection function
- Type assertions can be used on unknown types
ts
const value: unknown = "Hello World";
const someString: string = value as string;8.4 The unknown type in union types
- In a union type, the unknown type absorbs any type.This means that if any of the component types is unknown, the union type will also be equivalent to unknown:
ts
type UnionType1 = unknown | null; // unknown
type UnionType2 = unknown | undefined; // unknown
type UnionType3 = unknown | string; // unknown
type UnionType4 = unknown | number[]; // unknown8.5 unknown type in intersection types
- In intersection types, any type can absorb the unknown type.This means that intersecting any type with unknown will not change the result type
ts
type IntersectionType1 = unknown & null; // null
type IntersectionType2 = unknown & undefined; // undefined
type IntersectionType3 = unknown & string; // string
type IntersectionType4 = unknown & number[]; // number[]
type IntersectionType5 = unknown & any; // any8.6 never is a subtype of unknown
ts
type isNever = never extends unknown ? true : false;8.7 keyof unknown equals never
ts
type key = keyof unknown;8.8 Only wait or wait operations can be performed on unknown, but no other operations can be performed.
ts
un1 === un2;
un1 !== un2;
un1 += un2;8.9 No operations can be performed
- Cannot access property
- cannot be called as a function
- Cannot be used as a constructor of a class and cannot create instances
ts
un.name;
un();
new un();8.10 Mapping properties
- If the mapping type is unknown during traversal, the attributes will not be mapped.
ts
type getType<T> = {
[P in keyof T]: number;
};
type t = getType<unknown>;