Distributive Conditional Types

Focus on reading: www.typescriptlang.org/docs/handbo…

Some of the behavior of extends: juejin.cn/post/684490…

In the case where T extends U, both types are union types and behave oddly

Essentially, the extends behavior is broken down into: ‘a’ (T) extends the ‘a’ (U), ‘a’ (T) extends’ c ‘(U),’ b ‘(T) extends the’ a ‘(U),’ b ‘(T) extends’ c’ (U), C is’ true ‘when all satisfy extends.

This kind of understanding seems to work in all of the advanced types below.

type T = 'a' | 'b'
type U = 'a' | 'c'
type C = T extends U ? 'true' : 'false'
Copy the code

Partical

type Partical<T> = { [K in keyof T]? : T[k] }Copy the code

Required

– symbols:

1. -? Erase the optional

2. -readonly Removes the readonly

type Required<T>{ [K in keyof T]-? : T[K] }Copy the code

Readonly

type Readonly<T>{
    readonly [K in keyof T]: T[K]
}
Copy the code

Record

/ / key type string | number | symbol / / keyof returns an object of key, Type key = keyof any type Record <K extends keyof any, T> = {[P in K]: T}Copy the code

Pick

Pick is the key selected from the given T.

Attributes cannot be omitted

type Pick<T, K extends keyof T> = {
    [P in K]: T[P]
}
Copy the code

Exclude

Apply to Union types, remove Union from Type

type Exclued<T, U> = T extends U ? never : T 
Copy the code

Omit

Get all Keys from Type, and then remove Keys from Keys

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
Copy the code

Extract

Extract all Union types that can be assigned to Union from Type

type Extract<T, U> = T extends U ? T : never
Copy the code

NonNullable

type NonNullable<T> = T extends null | undefined ? never : T
Copy the code

Parameters

Gets the types of function arguments (expressed as tuples)

Extends here ensures that T is a function

type Parameters<T extends (... args: any) => any> = T extends (... arg: infer P) => any : P : neverCopy the code

ConstructorParameters

Gets the parameter types of the constructor, so the type is narrowed down to the constructor.

Why do we add abstract here?

type Parameters<T extends abstract new (... args: any) => any> = T extends abstract new (... arg: infer P) => any : P : neverCopy the code

ReturnType

type ReturnType<T extends (... args: any) => any> = T extends (... args: any) => infer R ? R : anyCopy the code

InstanceType

Gets the type returned by the constructor, the constructor version of ReturnType

type InstanceType<T extends abstract new (... args: any) => any> = T extends abstract new (... arg: any) => infer R : R ? anyCopy the code

ThisParameterType

Gets the type of this for the function, returning unknown if it does not exist (for example, the arrow function)

type ThisParameterType<T> = T extends (this: infer U, ... args: any[]) => any ? U : unknown function toHex(this: Number){ return this.toString(16) } function numberToString(n: ThisParameterType<typeof toHex>){ return toHex.apply(n) }Copy the code

OmitThisParameter

If function is of type this, return T

2. If this type exists, it has been processed by ThisParameterType and this is removed. Continue to verify that this was retrieved, and if so return function type with derived type; Otherwise return T.

type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (... args: infer A) => infer R ? (... args: A) => R : T function toHex(this: Number){return this.tostring (16)} And then set up a new context by const fiveToHex: OmitThisParameter < typeof toHex > = toHex. Bind (5) fiveToHex ()Copy the code

Verify that ThisParameterType changes the type of function

function toHex(this: {return this.tostring (16)} type test = ThisParameterType<typeof toHex> Get 1 toHex(6) // carsh error: void this cannot be assigned to Number type this toHex()Copy the code

Pay attention to

1. Only one parameter named this can exist in TS

2. The position of this parameter must be the first

ThisType

Marker for contextual ‘this’ type: Saves the function’s this type and does nothing with the type.

The –noImplicitThis option must be enabled

inerface ThisType<T>{}
Copy the code

This Type sets the context of the methods to d&m, which is an object of Type <D, M>.

type ObjectDescriptor<D, M> = { data? : D; Methods: M & ThisType<D & M>} function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M { let data: object = desc.data || {} let methods: object = desc.methods || {} return {... data, ... methods} as D & M } let obj = makeObject({ data : {x: 0, y: 0}, methods: { moveBy(dx: number, dy: Number){// when ThisType is added, the this type of moveBy method is strengthened // This. X cannot exist in moveBy when the makeObject function handles the sign // ThisType is present, D&m this.x += dx; this.y += dy; }}}) // After the structure directly beat flat obj.x = 10; obj.y = 20; obj.moveBy(5, 5);Copy the code

The following four methods are slightly, see: www.typescriptlang.org/docs/handbo…

  • Uppercase
  • Lowercase
  • Capitalize
  • Uncapitalize

The last

www.zhihu.com/question/47…