preface
TypeScript has some common tool types built into it that make it a lot easier for developers to use. Before we learn about tool types, we need to understand the use of advanced types.
High-level types
Unlike basic types, advanced types allow us to manipulate and define types flexibly.
Cross type (&)
Cross typing is merging multiple types into one type.
type PersonType = { name: string; id: number} and {age: number }
const person: PersonType = {
id: 1.name: 'lisi'.age: 18
}
Copy the code
The joint type (|)
The union type indicates that the value can be one of many types.
interface Button {
type: 'default' | 'primary' | 'danger'
text: string
}
const btn: Button = {
type: 'primary'.// Type can be 'default', 'primary' or 'danger'
text: 'button'
}
Copy the code
Type Alias (Type)
If you need to use the previously mentioned cross and union types in more than one place, you need to declare an alias for the two types in the form of a type alias.
type ButtonType = type: 'default' | 'primary' | 'danger'
Copy the code
Type index (KEYOF)
Keyof is similar to Object.keys. This operator can be used to get all keys of a type whose return type is the union type.
interface Person {
name: string;
age: number; id? :number;
}
type K1 = keyof Person // name | age | id
type K2 = keyof Person[]; // "length" | "push" | "pop" | "concat" | ...
type K3 = keyof { [x: string]: Person }; // string | number
Copy the code
Type constraint (extends)
Extends extends can be used to extend a class or an interface, but it can also be used to determine conditional types. Type constraints, in a nutshell, narrow down the range of data types that can be embodied by a type.
type Words = 'a'|'b'|"c";
type W<T> = T extends Words ? true : false;
type WA = W<'a'>; // -> true
type WD = W<'d'>; // -> false
Copy the code
Type mapping (in)
In is used to iterate over enumerated types.
type Keys = "a" | "b" | "c"
type Obj = {
[p in Keys]: any
} // -> { a: any, b: any, c: any }
Copy the code
Condition types (U? X, Y)
Conditional types have the same syntax as ternary expressions and are often used in cases where the type is uncertain.
type Extract<T, U> = T extends U ? T : never;
Copy the code
infer
Infer represents keywords that appear as placeholders in the extends condition statement to modify data types. The modified data types cannot be inferred until they are used.
9. Infer:
infer
Appear in theextends
The parameter type position of the function type after the conditional statementinfer
Appear in theextends
On the function return value type after the conditional statementinfer
Occurs on the generic embodiment of a type
type ParamType<T> = T extends(... args: infer P) =>any ? P : T;
Copy the code
interface User {
name: string;
age: number;
}
type Func = (user: User) = > void;
type Param = ParamType<Func>; // Param = User
type AA = ParamType<string>; // string
Copy the code
Built-in types
Let’s take a look at what tool paradigms are built into TS.
Partial
Partial is you can make all the properties of a type optional, right? .
Source:
type Partial<T> = {
[P inkeyof T]? : T[P]; };Copy the code
Example:
interface IUser {
name: string;
age: number;
sex: number;
}
type UserType = Partial<IUser>
typeUserType = { name? :string | undefined; age? :number | undefined; sex? :number | undefined;
}
Copy the code
Required
Required is the opposite of Partial, which changes all attributes to optional, and Required, which changes all types to Required.
Source:
type Required<T> = {
[P inkeyof T]-? : T[P]; };Copy the code
Example:
type UserType2 = Required<UserType>
type UserType2 = {
name: string;
age: number;
sex: number;
}
Copy the code
Among them -? Does it stand for removal? The modifier logo.
And that corresponds to a plus, right? This meaning is naturally related to -? Instead, it was used to make properties optional, + can be omitted, see Partial.
Readonly
The purpose of this type is to make the passed property a read-only option.
Source:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Copy the code
Example:
type UserType3 = Readonly<UserType>
type UserType3 = {
readonly name: string;
readonly age: number;
readonly sex: number;
}
Copy the code
Add a readonly identifier to the child attribute. If you change the above readonly to -readonly, you remove the readonly identifier for the child attribute.
Pick
This type can pick out the subattributes of a type and turn them into subtypes that contain some of the attributes of that type.
Source:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Copy the code
Example:
interface Todo {
title: string
completed: boolean
description: string
}
type TodoPreview = Pick<Todo, "title" | "completed">
const todo: TodoPreview =
title: 'Clean room'.completed: false
}
Copy the code
Record
This type converts the values of all attributes in K to type T.
Source:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Copy the code
Example:
type T = Record<'a' | 'b' | 'c', Person>; // -> { a: Person; b: Person; c: Person; }
Copy the code
Exclude
Exclude Removes a type that belongs to another type.
Source:
type Exclude<T, U> = T extends U ? never : T;
Copy the code
Example:
type T1 = Exclude<'a' | 'b' | 'c' | 'd'.'a' | 'c' | 'f'>; // -> 'b' | 'd'
Copy the code
Extract
Extract is used to Extract the element T contains in U, or more semantically Extract U from T.
Source:
type Extract<T, U> = T extends U ? T : never
Copy the code
Example:
type T2 = Extract<string | number | symbol, string | number> // string | number
Copy the code
ReturnType
This type is used to get the return type of a function.
Source:
type ReturnType<T extends(... args:any[]) = >any> =
T extends(... args:any[]) => infer R ? R : any;
Copy the code
Example:
function bar(x: string) :Array<string> {
return [x];
}
type fn = ReturnType<typeof bar>; // -> string[]
Copy the code
ThisType
This type is used to specify the context object type.
Source:
interface ThisType<T> { }
Copy the code
The declaration has only one interface and no implementation, indicating that this type is supported at the TS source level, rather than through type conversion.
Example:
interface Person {
name: string;
age: number;
}
const obj: ThisType<Person> = {
dosth() {
this.name // string}}Copy the code
In this case, you can specify that context objects in all methods in obj should be of type Person. Note that when using ThisType
, you must ensure that the –noImplicitThis flag is set to true.
InstanceType
This type is used to get the instance type of the constructor type.
Source:
type InstanceType<T extends new(... args:any[]) = >any> =
T extends new(... args:any[]) => infer R ? R : any;
Copy the code
Example:
class C {
x = 0;
y = 0;
}
type T1 = InstanceType<typeof C>; // C
type T2 = InstanceType<any>; // any
type T3 = InstanceType<never>; // any
type T4 = InstanceType<string>; // Error
type T5 = InstanceType<Function>; // Error
Copy the code
NonNullable
This type can be used to filter null and undefined types in types.
Source:
type NonNullable<T> = T extends null | undefined ? never : T;
Copy the code
Example:
type T1 = string | number | null;
type T2 = NonNullable<T1>; // -> string | number;
Copy the code
Parameters
This type gets the tuple type of the parameter types of the function.
Source:
type Parameters<T extends(... args:any[]) = >any> =
T extends(... args: infer P) =>any ? P : never;
Copy the code
Example:
function bar(x: string) :Array<string> {
return [x];
}
type P = Parameters<typeof bar>; // -> [number]
Copy the code
The true type of P is the tuple type [number] of the arguments to foo.
ConstructorParameters
This type is used to get the tuple type of the class’s parameter types, and simply get the class constructor parameter types.
Source:
type ConstructorParameters<T extends new(... args:any[]) = >any> =
T extends new(... args: infer P) =>any ? P : never; \Copy the code
Example:
class Person {
private firstName: string;
private lastName: string;
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName; }}type P = ConstructorParameters<typeof Person>; // -> [string, string]
Copy the code
User-defined common types
Here are some of the more useful non-built-in generic tool types.
Omit
Omit
is used to construct a new type using all properties of type T except type K.
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Copy the code
Example:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo, "description">;
const todo: TodoPreview = {
title: "room".completed: false};Copy the code
Mutable
To remove readonly for all attributes:
type Mutable<T> = {
-readonly [P in keyof T]: T[P]
}
Copy the code
Deferred
Same property name, but make the value a Promise instead of a concrete value:
type Deferred<T> = {
[P in keyof T]: Promise<T[P]>;
};
Copy the code
DeepReadonly
DeepReadonly is used to deeply traverse T and make all its properties read-only.
Source:
type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> }
Copy the code
Example:
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
interface A {
B: { C: number; };
D: { E: number; } []; }const myDeepReadonlyObject: DeepReadonly<A> = {
B: { C: 1 },
D: [{E: 2 } ],
}
myDeepReadonlyObject.B = { C: 2 }; // error :)
myDeepReadonlyObject.B.C = 2; // error :)
Copy the code
The underlying attribute of the constraint variable is read-only.
ConvertNumberToString
ConvertNumberToString is used to ConvertNumberToString.
type ConvertNumberToString<T> = {
[K in keyof T]: T[K] extends string ? string : T[K]
}
Copy the code
ValueOf
ValueOf corresponds to keyof. Fetches all values of the specified type.
type ValueOf<T> = T[keyof T]
Copy the code
PowerPartial
The built-in Partial has a limitation that it only supports the first layer of attributes. If you have nested multiple layers of attributes, it does not work.
type PowerPartial<T> = {
// If object is a recursive type
[U inkeyof T]? : T[U]extends object
? PowerPartial<T[U]>
: T[U]
};
Copy the code
Deferred
Same property name, but make the value a Promise instead of a concrete value:
type Deferred<T> = {
[P in keyof T]: Promise<T[P]>;
};
Copy the code
Proxify
Add a proxy for the property of T:
type Proxify<T> = {
[P in keyof T]: { get(): T[P]; set(v: T[P]): void}};Copy the code
PromiseReturnType
Gets the return value type of the Promise.
Source:
type PromiseReturnType<T extends Promise<any>> =
T extends Promise<infer R> ? R : any;
Copy the code
Example:
type MyPromise = Promise<string>
type T = PromiseReturnType<MyPromise> /// string
Copy the code
Overwrite
The latter type overwrites the existing parameters of the former type.
Source:
type Overwrite<T, U> = {
[K in keyof T]: K extends keyof U ? U[K] : T[K];
};
Copy the code
Example:
type Props = { name: string; age: number; visible: boolean };
type NewProps = { age: string; other: string };
type ReplacedProps = Overwrite<Props, NewProps>;
// { name: string; age: string; visible: boolean; }
Copy the code
Refer to the article
- Comb through TypeScript’s built-in tool generics
- TypeScript’s powerful type aliases
- TypeScript advanced types you don’t know about