Since there aren’t many advanced types officially available, let’s explain them all to make our development more efficient. Partial, Readonly, Record, and Pick are the most frequently used ones in Typescript, so they are not repeated here.

Note: Advanced type declarations, including conditional types, mapping types, type inferences, and never types, have been shared before, as you can see in my column. (In fact, the previous reading is a prerequisite for introducing the official high-level type)

These are advanced types that you probably won’t use, but a quick look at what TS presets will do, and when certain open scenarios come to mind, it’s always a pleasant surprise. (These features are written based on v3.8-beta.)

Required< T >

/** * Make all properties in T required */
type Required<T> = {
    [P inkeyof T]-? : T[P]; };Copy the code

Contrary to what Partial

program types do, make all type attributes mandatory.

type Coord = Required<{ x: number, y? :number} >./ / is equivalent to
type Coord = {
	x: number;
	y: number;
}
Copy the code

Mainly because -? The ability to map conditional decorators, removing all optional parameter states. More decorators address TypeScript Mapped types (e.g. {[P in K]: T[P]}) that can be shared previously.

Exclude<T, U>

/** * Exclude from T those types that are assignable to U */
type Exclude<T, U> = T extends U ? never : T;
Copy the code

Exclude a subtype specified in a union type:

type T0 = Exclude<'a' | 'b' | 'c'.'b'> // 'a' | 'c'
type T1 = Exclude<string | number | boolean.boolean> // string | number
Copy the code

This is primarily a parse-deferred feature based on the extends condition type, which returns all candidate types other than a match, combined with the null value feature of the never type to implement this advanced type.

Extract<T, U>

/** * Extract from T those types that are assignable to U */
type Extract<T, U> = T extends U ? T : never;
Copy the code

The complete opposite of Exclude

, used to extract the specified union type or return never if no extract type exists. Can be used to determine whether a complex union type contains a specified subtype:
,>

type T0 = Extract<'a' | 'b' | 'c'.'a'> // 'a'
type T1 = Extract<string | number | boolean.boolean> // boolean
Copy the code

Omit<T, K extends keyof any>

/** * Construct a type with the properties of T except for those in type K. */
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Copy the code

Exclude attributes specified in the interface:

interface I1 {
	a: number;
	b: string;
	c: boolean;
}

type AC = Omit<I1, 'b'>;     // { a:number; c:boolean } 
type C = Omit<I1, 'a' |'b'>  // { c: boolean }
Copy the code

This is also used more frequently in advanced types.

NonNullable< T >

/** * Exclude null and undefined from T */
type NonNullable<T> = T extends null | undefined ? never : T;
Copy the code

Filter null and undefined from union types:

type T1 = NonNullable<string | null | undefined>; // string
Copy the code

As an additional note, null and undefined can be assigned to any type due to their special nature, which can cause unexpected errors. When you enable –strictNullChecks, TS checks strictly and can only be assigned if it is declared null:

/ / close - strictNullChecks
let s: string = "foo";
s = null; / / normal

/ / open - strictNullChecks
s = null; // Error: Type 'null' is not assignable to type 'string'. 
Copy the code

Parameters<T extends (… args: any) => any>

/** * Obtain the parameters of a function type in a tuple */
type Parameters<T extends(... args:any) = >any> = T extends(... args: infer P) =>any ? P : never;
Copy the code

Gets all the argument types of the function, as tuples:

type F1 = (a: string, b: number) = > void;

type F1ParamTypes = Parameters(F1);  // [string, number]
Copy the code

If you want to see how this works, look at the Infer type inference capability of TypeScript conditional types we shared earlier.

ConstructorParameters<T extends new (… args: any) => any>

/** * Obtain the parameters of a constructor function type in a tuple */
type ConstructorParameters<T extends new(... args:any) = >any> = T extends new(... args: infer P) =>any ? P : never;
Copy the code

The type is similar, except that all the arguments to the constructor are taken. About constructor declarations and how to use this advanced type:

interfaceIEntity { count? :(a)= > number
}

interface IEntityConstructor {
    new (a: boolean, b: string): IEntity;
}

class Entity implements IEntity {
    constructor(a: boolean, b: string) {}}type EntityConstructorParamType = ConstructorParameters<IEntityConstructor>; // [boolean, string]
Copy the code

What does the IEntityConstructor interface do here? It comes in handy when based on creating instance functions:

function createEntity(ctor: IEntityConstructor, ... arg: EntityConstructorParamType) :IEntity {
    return newctor(... arg); }const entity = createEntity(Entity, true.'a');
Copy the code

ReturnType<T extends (… args: any) => any>

/** * Obtain the return type of a function type */
type ReturnType<T extends(... args:any) = >any> = T extends(... args:any) => infer R ? R : any;
Copy the code

Receives a function declaration and returns the return value type of the function, or a combined type if there are multiple types:

type F1 = (a)= > Date;

type F1ReturnType = ReturnType<F1>; // Date
Copy the code

InstanceType<T extends new (… args: any) => any>

/** * Obtain the return type of a constructor function type */
type InstanceType<T extends new(... args:any) = >any> = T extends new(... args:any) => infer R ? R : any;
Copy the code

Gets the return type of the constructor, or if there are more than one, returns it as a union type, using the above definition:

type EntityType = InstanceType<IEntityConstructor>; // IEntity
Copy the code

ThisParameterType< T >

/** * Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter. */
type ThisParameterType<T> = T extends (this: infer U, ... args:any[]) = >any ? U : unknown;
Copy the code

Returns the data type of this in the function, or unknown if none exists:

interface Foo {
    x: number
};

function fn(this: Foo) {}

type Test = ThisParameterType<typeof fn>; // Foo
Copy the code

Since we can declare this of a function in TS, this method is used to get this declaration, specifically using:

fn.bind({ x: 1 });   / / normal

fn.bind({ x: '1' }); // Error: ... Type 'string' is not assignable to type 'number'...
Copy the code

OmitThisParameter< T >

/** * Removes the 'this' parameter from a function type. */
type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends(... args: infer A) => infer R ?(. args: A) = > R : T;
Copy the code

Remove this data type from function:

interface Foo {
    x: number
};

type Fn = (this: Foo) = > void

type NonReturnFn = OmitThisParameter<Fn>; // () => void
Copy the code

Function types declaring this class have the following effects:

function f(this: void) {} // This declaration cannot be used within functions
Copy the code