First, common skills
1. Function overload
export function util(str: string) :string
export function util(str: number) :number
export function util(str: string | number) :number | string {
return str;
}
const a: string = util('a');
const b: number = util(1);
Copy the code
2. Capture variable types
The typeof a variable is captured through the typeof keyword
let a = 123;
let b = { x: 0.y: 1 };
type A = typeof a; / / number type
type B = typeof b; // { x: number, y: number }
Copy the code
3. Function bindingthis
context
Specify the context of the current function by binding the function’s first argument, this (official documentation)
const obj = {
say(name: string) {
console.log('Hello,', name); }}// Bind the current function context with the first argument this
function foo(this: typeof obj, str: string) {
this.say(str);
}
Copy the code
4. Never use
Never represents types that Never occur (official documentation), such as returns from throw functions, returns from dead-loop functions
// Throw an exception
function unexpected() :never {
throw Error('Unexpected');
}
function test(x: boolean) :number {
if (x) {
return 1;
}
unexpected(); // Since never represents a type that never occurs, number is not required as a return value
}
// The official documentation gives an example of an infinite loop
function infiniteLoop() :never {
while (true) {}}Copy the code
5. Index signature
interface A {
x: number
}
const a: A = {x: 1}
// The interface key type is string and the value type is Boolean
interface B {
[key: string] :boolean
}
const b: B = {
a: true.b: false
}
// in indicates traversal. The key names include 'a', 'b', and 'c'. The value type is string
type C = {
[key in 'a' | 'b' | 'c'] :string
}
const c: C = {
a: '1'.b: '2'.c: '3'
}
Copy the code
6. Access the type by index
(Official document)
interface A {
a: string
b: {
c: boolean}}type Aa = A['a'] / / type string
type Abc = A['b'] ['c'] / / a Boolean type
Copy the code
// Extract the type corresponding to the primitive
type B = [string.number]
type B0 = B[0] / / type string
type B1 = B[1] / / number type
Copy the code
// Extract the element type of the array
type C = Array<string | number | boolean>
// Get the array element type by accessing any index of the array type
type D = C[0] / / type (string | number | Boolean)
Copy the code
7. Useas
The as keyword can be used to specify the type of the value, which can easily handle some ambiguous scenarios
function foo(str? :string) {
return str.toString();
}
const obj = {
toString() {
}
}
foo(obj as string)
Copy the code
8. Condition types
As the name implies, a conditional type determines which type to use based on a condition (official document). The condition type looks something like this: T extends U? X : Y
// If T is of type string, return string, otherwise return number
type F<T> = T extends string ? string : number
const a: F<string> = 'abc'; // If the type of the generic is string, it is string
const b: F<number> = 1; // The generic type is of type number if it is not string
const c: F<boolean> = 2; // The generic type is of type number if it is not string
Copy the code
Use 9.is
The keyword is used for type protection
// Returns type Boolean, and tells the compiler to return true if value is of type string
function isString(value: any) :value is string {
return typeof value === 'string';
}
function fn(val: number | string) {
if (isString(val)) { // If this is true, val is of type string
val.trim();
} else { // Otherwise, val is number
val.toFixed(2); }}Copy the code
The official array. isArray method definition uses the is keyword:
interface ArrayConstructor {
isArray: (arg: any) = > arg is any[];
}
Copy the code
10. Define class attributes by modifying constructor parameters
Constructor parameters can be modified to quickly define class attributes and automatically assign values, as shown in the following example:
class Point {
constructor(private x: number.private y: number){}}Copy the code
class Point {
private x: number
private y: number
constructor(x: number, y: number) {
this.x = x;
this.y = y; }}Copy the code
The above two methods are equivalent, but the above one can write less code. In addition to modifying constructor parameters with private, other similar modifying keywords are public, protected, and readonly, as described in the official documentation
Second, generic
Generics can provide more flexible type constraints than being limited to one type. Commonly used in function, class, interface, type (official documentation)
1. Example
function
function foo<T> (arg: T) :T {
return arg;
}
Copy the code
class
class Foo<T> {
name: T
constructor(name: T) {
this.name = name;
}
getName(): T {
return this.name
}
}
const foo = new Foo<number> (3);
const name: number = foo.getName();
Copy the code
interface
interface Foo<T> {
a: T
}
const foo: Foo<number> = { a: 1 }
Copy the code
type
type Foo<T> = { a: T }
const foo: Foo<boolean> = { a: false }
Copy the code
2. Generic constraints
Generics can be constrained by the extends keyword
/ / specify the type of the generic limited to: string | number, other types will be an error
interface A<T extends string | number> {
[key: string]: T
}
const a: A<string> = {a: 'abc'}
const b: A<number> = {a: 123}
Copy the code
3. Specify the generic default type
interface B<T = number> {
[key: string]: T
}
const c: B = { a: 123 }
const d: B<string> = { a: 'abc' }
Copy the code
Some TypeScript operators
Here’s a look at some of the TypeScript operators to help you understand what follows
?
: Indicates an optional parameter or attribute. It can be used for function parameters or interface attributes-?
: Deselect optional flags (extension: similar-readonly
Cancels the readonly flag)in
: indicates the traversal typetypeof
: Captures variable types, as shown abovekeyof
: A collection of strings or numbers that generate the keys of an object type, often within
Use a combination ofinfer
: indicates inferred types. The TS built-in types are described belowParameters
There will be concrete examples when you implement it
Implement TypeScript built-in types
TypeScript provides some common types that developers can use directly. Here’s how these types are implemented (built-in types use documentation)
1. Record
Construct a key-value pair type with key K and value T
/ / keyof any include: string | number | symbol
type Record<K extends keyof any, T> = {
/ / said key type is constrained in K (string | number | symbol) of one or more of the value type for T
// in indicates traversal
[P in K]: T
}
const foo: Record<string.boolean> = {
a: true
}
const bar: Record<'x' | 'y'.number> = {
x: 1.y: 2
}
Copy the code
2. Partial
Makes all attributes in T optional
type Partial<T> = {
// Add all attributes of primitive type T to? Embellish, make optional
[P inkeyof T]? : T[P] }interface Foo {
a: string
b: number
}
const foo: Partial<Foo> = {
b: 2 // 'a' is no longer necessary
}
Copy the code
3. Required
In contrast to Partial, make all attributes in T required
type Required<T> = {
// Add -? To all attributes of primitive type T. Embellish, become necessary
/ / -? Student: Move out? This logo
[P inkeyof T]-? : T[P] }interface Foo {
a: stringb? :number
}
const foo: Required<Foo> = {
a: 'abc'.b: 2 // 'b' has become mandatory
}
Copy the code
4. Readonly
Make all properties in T read only
type Readonly<T> = {
// Add the readonly modifier to all attributes of the primitive type T, making the attributes read-only
readonly [P in keyof T]: T[P]
}
interface Foo {
a: string
}
const foo: Readonly<Foo> = {
a: 'abc'
}
// foo.a = 'def' // Read-only and unmodifiable
// In addition, you can use the -readonly modifier to remove the readonly modifier
type Writable<T> = {
-readonly [P in keyof T]: T[P]
}
interface Bar {
readonly a: string
}
const bar: Writable<Bar> = {
a: 'abc'
}
bar.a = 'def'; // 'Bar['a'] has readonly modifier removed
Copy the code
5. Pick
Select properties from type T that come from set K
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
interface Foo {
a: string
b: number
c: boolean
}
const foo: Pick<Foo, 'b' | 'c'> = {
b: 1.c: false
}
Copy the code
6. Exclude
Exclude types from T that can be assigned to U
// If T is a subtype of U, return never, otherwise return T
type Exclude<T, U> = T extends U ? never : T
/ / 'a' | 'b' | 'c' exclude list 'b', only 'a' or 'c'
let foo: Exclude<'a' | 'b' | 'c'.'b'> = 'a'
foo = 'c'
Copy the code
7. Extract
In contrast to Exclude, extract the type T can assign to U
// Return T if T is a subtype of U, otherwise return never
type Extract<T, U> = T extends U ? T : never
/ / 'a' | 'b' | 'c' extract 'b', only for the 'b'
let foo: Extract<'a' | 'b' | 'c'.'b'> = 'b'
Copy the code
8. Omit
I’m going to omit some of the properties in T that come from the set K
// 1. Remove K from T attributes to get the rest of the set of attributes
// 2. Select the remaining set from T
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
interface Foo {
a: string
b: number
c: boolean
}
// Omit 'c' from Foo, leaving Foo with 'a' and 'b'
let foo: Omit<Foo, 'c'> = {
a: 'a'.b: 1
}
Copy the code
9. NonNullable
Exclude null and undefined types
/ / exclude null | is undefined
type NonNullable<T> = T extends null | undefined ? never : T
type Foo = string | null
const a: NonNullable<Foo> = 'a' // Cannot be assigned to null or undefined
Copy the code
10. Parameters
Returns the corresponding tuple type based on the function’s arguments
Infer P is used to indicate function parameters to be inferred
type Parameters<T extends(... args:any) = >any> = T extends(... args: infer P) =>any ? P : never
type Foo = (a: string, b: number) = > void
const a: Parameters<Foo> = ['a'.1] // tuple [string, number]
Copy the code
11. ConstructorParameters
Returns the corresponding tuple type based on the constructor’s arguments
// Similar to Parameters
type ConstructorParameters<T extends new(... args:any) = >any> = T extends new(... args: infer P) =>any ? P : never
interface Foo {
new(a: string.b: number)}const a: ConstructorParameters<Foo> = ['a'.1] // tuple [string, number]
Copy the code
12. ReturnType
Returns the return type of the function
// Similar to Parameters
type ReturnType<T extends(... args:any) = >any> = T extends(... args:any) => infer R ? R : any
type Foo = () = > boolean
const a: ReturnType<Foo> = true // Return Boolean
Copy the code
13. InstanceType
// Similar to Parameters
type InstanceType<T extends new(... args:any) = >any> = T extends new(... args:any) => infer R ? R : any
Copy the code
Refer to the link
- TypeScript manual reference
- Understand TypeScript in depth
- A brief description of built-in types in TS