前端TypeScript

Typescript 内置类型

约 3665 字大约 12 分钟

typescript

2022-03-15

TypeScript 提供了许多内置的类型方法和工具类型,用于处理和操作类型。以下是其中一些常用的内置类型方法:

分类

Utility Types(工具类型)

  • Partial<T> : 将类型 T 的所有属性变为可选。
  • Required<T> : 将类型 T 的所有属性变为必选。
  • Readonly<T> : 将类型 T 的所有属性变为只读。
  • Record<K, T> : 创建一个具有指定键类型 K 和值类型 T 的新对象类型。
  • Pick<T, K> : 从类型 T 中选择指定属性 K 形成新类型。
  • Omit<T, K> : 从类型 T 中排除指定属性 K 形成新类型。
  • Exclude<T, U> : 从类型 T 中排除可以赋值给类型 U 的类型。
  • Extract<T, U> : 从类型 T 中提取可以赋值给类型 U 的类型。
  • NonNullable<T> : 从类型 T 中排除 null 和 undefined 类型。
  • ReturnType<T> : 获取函数类型 T 的返回类型。
  • Parameters<T> : 获取函数类型 T 的参数类型组成的元组类型。
  • Awaited<T>: 模拟 async 函数中的 await 操作,或者 promise 上的 .then() 方法。
  • ConstructorParameters<T>: 获取构造函数类型 T 的参数类型组成的元组类型。
  • InstanceType<T>: 获取构造函数类型 T 的实例类型。
  • ThisParameterType<T>: 获取函数类型 T 的 this 类型。
  • OmitThisParameter<T>: 从函数类型 T 中移除 this 类型。
  • ThisType<T>: 获取函数类型 T 的 this 类型。

条件判定类型

  • Conditional Types(条件类型): 根据类型关系进行条件判断生成不同的类型。
  • Distribute Conditional Types(分布式条件类型): 分发条件类型,允许条件类型在联合类型上进行分发。

Mapped Types(映射类型)

根据已有类型创建新类型,通过映射类型可以生成新的类型结构。

Template Literal Types(模板文字类型)

使用字符串模板创建新类型。

类型推断关键字

  • typeof: 关键字允许在条件类型中推断类型变量。
  • keyof:关键字允许在泛型条件类型中推断类型变量。
  • instanceof:运算符用于检查对象是否是特定类的实例。
  • in:用于检查对象是否具有特定属性。
  • type guard:类型守卫是自定义的函数或条件语句,用于在代码块内缩小变量的类型范围。
  • as:用于类型断言,允许将一个变量断言为特定的类型。

Utility Types

Partial<T>

构造一个将 T 的所有属性设置为可选的类型。

interface Todo {
  Todo.title: stringtitle: string
  Todo.description: stringdescription: string
}

function function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>): {
    title: string;
    description: string;
}updateTodo(todo: Todotodo: Todo, fieldsToUpdate: Partial<Todo>fieldsToUpdate: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<Todo>) {
return { ...todo: Todotodo, ...fieldsToUpdate: Partial<Todo>fieldsToUpdate } } const const todo1: { title: string; description: string; }todo1 = { title: stringtitle: 'organize desk', description: stringdescription: 'clear clutter', }; const const todo2: { title: string; description: string; }todo2 = function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>): { title: string; description: string; }updateTodo(const todo1: { title: string; description: string; }todo1, { description?: string | undefineddescription: 'throw out trash', }); //

Required<T>

该类型将类型 T 的所有属性变为必选。

interface Props {
  Props.a?: number | undefineda?: number
  Props.b?: string | undefinedb?: string
}
const const obj: Propsobj: Props = { Props.a?: number | undefineda: 5 }
const obj2: type Required<T> = { [P in keyof T]-?: T[P]; }
Make all properties in T required
Required
<Props> = { a: numbera: 5 }
Property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.

Readonly<T>

将类型 T 的所有属性变为只读。

interface Todo {
  Todo.title: stringtitle: string
}
const const todo: Readonly<Todo>todo: type Readonly<T> = { readonly [P in keyof T]: T[P]; }
Make all properties in T readonly
Readonly
<Todo> = {
title: stringtitle: 'Delete inactive users', } const todo: Readonly<Todo>todo.title = 'Hello'
Cannot assign to 'title' because it is a read-only property.

Record<K, T>

创建一个具有指定键类型 K 和值类型 T 的新对象类型。

interface CatInfo {
  CatInfo.age: numberage: number
  CatInfo.breed: stringbreed: string
}
type type CatName = "miffy" | "boris" | "mordred"CatName = 'miffy' | 'boris' | 'mordred'

const const cats: Record<CatName, CatInfo>cats: type Record<K extends string | number | symbol, T> = { [P in K]: T; }
Construct a type with a set of properties K of type T
Record
<type CatName = "miffy" | "boris" | "mordred"CatName, CatInfo> = {
miffy: CatInfomiffy: { CatInfo.age: numberage: 10, CatInfo.breed: stringbreed: 'Persian' }, boris: CatInfoboris: { CatInfo.age: numberage: 5, CatInfo.breed: stringbreed: 'Maine Coon' }, mordred: CatInfomordred: { CatInfo.age: numberage: 16, CatInfo.breed: stringbreed: 'British Shorthair' }, }; const cats: Record<CatName, CatInfo>cats.
boris: CatInfo
boris
//

Pick<T, K>

从类型 T 中选择指定属性 K 形成新类型。

interface Todo {
  Todo.title: stringtitle: string
  Todo.description: stringdescription: string
  Todo.completed: booleancompleted: boolean
}

type type TodoPreview = {
    title: string;
    completed: boolean;
}TodoPreview = type Pick<T, K extends keyof T> = { [P in K]: T[P]; }
From T, pick a set of properties whose keys are in the union K
Pick
<Todo, 'title' | 'completed'>
const const todo: TodoPreviewtodo: type TodoPreview = { title: string; completed: boolean; }TodoPreview = { title: stringtitle: 'Clean room', completed: booleancompleted: false, }
const todo: TodoPreview
todo
//

Omit<T, K>

与 Pick 相反,该类型从类型 T 中排除指定属性 K 形成新类型。

interface Todo {
  Todo.title: stringtitle: string;
  Todo.description: stringdescription: string;
  Todo.completed: booleancompleted: boolean;
  Todo.createdAt: numbercreatedAt: number;
}
 
type type TodoPreview = {
    title: string;
    completed: boolean;
    createdAt: number;
}TodoPreview = type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }
Construct a type with the properties of T except for those in type K.
Omit
<Todo, 'description'>
const const todo: TodoPreviewtodo: type TodoPreview = { title: string; completed: boolean; createdAt: number; }TodoPreview = { title: stringtitle: 'Clean room', completed: booleancompleted: false, createdAt: numbercreatedAt: 1615544252770, }
const todo: TodoPreview
todo
type type TodoInfo = { description: string; title: string; }TodoInfo = type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }
Construct a type with the properties of T except for those in type K.
Omit
<Todo, 'completed' | 'createdAt'>
const const todoInfo: TodoInfotodoInfo: type TodoInfo = { description: string; title: string; }TodoInfo = { title: stringtitle: 'Pick up kids', description: stringdescription: 'Kindergarten closes at 5pm', }
const todoInfo: TodoInfo
todoInfo
//

Exclude<T, U>

从类型 T 中排除可以赋值给类型 U 的类型。

type 
type T0 = "b" | "c"
T0
= type Exclude<T, U> = T extends U ? never : T
Exclude from T those types that are assignable to U
Exclude
<'a' | 'b' | 'c', 'a'>
type
type T1 = "c"
T1
= type Exclude<T, U> = T extends U ? never : T
Exclude from T those types that are assignable to U
Exclude
<'a' | 'b' | 'c', 'a' | 'b'>
type
type T2 = string | number
T2
= type Exclude<T, U> = T extends U ? never : T
Exclude from T those types that are assignable to U
Exclude
<string | number | (() => void), Function>
type type Shape = { kind: 'circle'; radius: number; } | { kind: 'square'; x: number; } | { kind: 'triangle'; x: number; y: number; }Shape = | { kind: "circle"kind: 'circle'; radius: numberradius: number } | { kind: "square"kind: 'square'; x: numberx: number } | { kind: "triangle"kind: 'triangle'; x: numberx: number; y: numbery: number } type
type T3 = { kind: 'square'; x: number; } | { kind: 'triangle'; x: number; y: number; }
T3
= type Exclude<T, U> = T extends U ? never : T
Exclude from T those types that are assignable to U
Exclude
<type Shape = { kind: 'circle'; radius: number; } | { kind: 'square'; x: number; } | { kind: 'triangle'; x: number; y: number; }Shape, { kind: "circle"kind: 'circle' }>
//

Extract<T, U>

从类型 T 中提取可以赋值给类型 U 的类型。

type 
type T0 = "a"
T0
= type Extract<T, U> = T extends U ? T : never
Extract from T those types that are assignable to U
Extract
<'a' | 'b' | 'c', 'a' | 'f'>
type
type T1 = () => void
T1
= type Extract<T, U> = T extends U ? T : never
Extract from T those types that are assignable to U
Extract
<string | number | (() => void), Function>
type type Shape = { kind: 'circle'; radius: number; } | { kind: 'square'; x: number; } | { kind: 'triangle'; x: number; y: number; }Shape = | { kind: "circle"kind: 'circle'; radius: numberradius: number } | { kind: "square"kind: 'square'; x: numberx: number } | { kind: "triangle"kind: 'triangle'; x: numberx: number; y: numbery: number } type
type T2 = { kind: 'circle'; radius: number; }
T2
= type Extract<T, U> = T extends U ? T : never
Extract from T those types that are assignable to U
Extract
<type Shape = { kind: 'circle'; radius: number; } | { kind: 'square'; x: number; } | { kind: 'triangle'; x: number; y: number; }Shape, { kind: "circle"kind: 'circle' }>
//

NonNullable<T>

从类型 T 中排除 null 和 undefined 类型。

type 
type T0 = string | number
T0
= type NonNullable<T> = T & {}
Exclude null and undefined from T
NonNullable
<string | number | undefined>
type
type T1 = string[]
T1
= type NonNullable<T> = T & {}
Exclude null and undefined from T
NonNullable
<string[] | null | undefined>
//

ReturnType<T>

获取函数类型 T 的返回类型。

declare function function f1(): {
    a: number;
    b: string;
}f1(): { a: numbera: number; b: stringb: string }

type 
type T0 = string
T0
= type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<() => string>
type
type T1 = void
T1
= type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<(s: strings: string) => void>
type
type T2 = unknown
T2
= type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<<function (type parameter) T in <T>(): TT>() => function (type parameter) T in <T>(): TT>
type
type T3 = number[]
T3
= type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<<function (type parameter) T in <T extends U, U extends number[]>(): TT extends function (type parameter) U in <T extends U, U extends number[]>(): TU, function (type parameter) U in <T extends U, U extends number[]>(): TU extends number[]>() => function (type parameter) T in <T extends U, U extends number[]>(): TT>
type
type T4 = { a: number; b: string; }
T4
= type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<typeof function f1(): { a: number; b: string; }f1>
type
type T5 = any
T5
= type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<any>
type
type T6 = never
T6
= type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<never>
type type T7 = anyT7 = type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<string>
Type 'string' does not satisfy the constraint '(...args: any) => any'.
type type T8 = anyT8 = type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<Function>
Type 'Function' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'.

Parameters<T>

获取函数类型 T 的参数类型组成的元组类型。

declare function function f1(arg: {
    a: number;
    b: string;
}): voidf1(arg: {
    a: number;
    b: string;
}arg: { a: numbera: number; b: stringb: string }): void

type 
type T0 = []
T0
= type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<() => string>
type
type T1 = [s: string]
T1
= type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<(s: strings: string) => void>
type
type T2 = [arg: unknown]
T2
= type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<<function (type parameter) T in <T>(arg: T): TT>(arg: Targ: function (type parameter) T in <T>(arg: T): TT) => function (type parameter) T in <T>(arg: T): TT>
type
type T3 = [arg: { a: number; b: string; }]
T3
= type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<typeof function f1(arg: { a: number; b: string; }): voidf1>;
type
type T4 = unknown[]
T4
= type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<any>
type
type T5 = never
T5
= type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<never>
type type T6 = neverT6 = type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<string>
Type 'string' does not satisfy the constraint '(...args: any) => any'.
type type T7 = neverT7 = type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Obtain the parameters of a function type in a tuple
Parameters
<Function>
Type 'Function' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'.

Awaited<T>

模拟 async 函数中的 await 操作,或者 promise 上的 .then() 方法。

type 
type A = string
A
= type Awaited<T> = T extends null | undefined ? T : T extends object & { then(onfulfilled: infer F, ...args: infer _): any; } ? F extends (value: infer V, ...args: infer _) => any ? Awaited<...> : never : T
Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
Awaited
<interface Promise<T>
Represents the completion of an asynchronous operation
Promise
<string>>
type
type B = number
B
= type Awaited<T> = T extends null | undefined ? T : T extends object & { then(onfulfilled: infer F, ...args: infer _): any; } ? F extends (value: infer V, ...args: infer _) => any ? Awaited<...> : never : T
Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
Awaited
<interface Promise<T>
Represents the completion of an asynchronous operation
Promise
<interface Promise<T>
Represents the completion of an asynchronous operation
Promise
<number>>>
type
type C = number | boolean
C
= type Awaited<T> = T extends null | undefined ? T : T extends object & { then(onfulfilled: infer F, ...args: infer _): any; } ? F extends (value: infer V, ...args: infer _) => any ? Awaited<...> : never : T
Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
Awaited
<boolean | interface Promise<T>
Represents the completion of an asynchronous operation
Promise
<number>>
//

ConstructorParameters<T>

获取构造函数类型 T 的参数类型组成的元组类型。

type 
type T0 = [message?: string | undefined, options?: ErrorOptions | undefined]
T0
= type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never
Obtain the parameters of a constructor function type in a tuple
ConstructorParameters
<ErrorConstructor>
type
type T1 = string[]
T1
= type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never
Obtain the parameters of a constructor function type in a tuple
ConstructorParameters
<FunctionConstructor>
type
type T2 = [pattern: string | RegExp, flags?: string | undefined]
T2
= type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never
Obtain the parameters of a constructor function type in a tuple
ConstructorParameters
<RegExpConstructor>
class class CC { constructor(a: numbera: number, b: stringb: string) {} } type
type T3 = [a: number, b: string]
T3
= type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never
Obtain the parameters of a constructor function type in a tuple
ConstructorParameters
<typeof class CC>
type
type T4 = unknown[]
T4
= type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never
Obtain the parameters of a constructor function type in a tuple
ConstructorParameters
<any>
type type T5 = neverT5 = type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never
Obtain the parameters of a constructor function type in a tuple
ConstructorParameters
<Function>
Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'. Type 'Function' provides no match for the signature 'new (...args: any): any'.

InstanceType<T>

获取构造函数类型 T 的实例类型。

class class CC {
  C.x: numberx = 0;
  C.y: numbery = 0;
}
 
type 
type T0 = C
T0
= type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any
Obtain the return type of a constructor function type
InstanceType
<typeof class CC>
type
type T1 = any
T1
= type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any
Obtain the return type of a constructor function type
InstanceType
<any>
type
type T2 = never
T2
= type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any
Obtain the return type of a constructor function type
InstanceType
<never>
type type T3 = anyT3 = type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any
Obtain the return type of a constructor function type
InstanceType
<string>
Type 'string' does not satisfy the constraint 'abstract new (...args: any) => any'.
type type T4 = anyT4 = type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any
Obtain the return type of a constructor function type
InstanceType
<Function>
Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'. Type 'Function' provides no match for the signature 'new (...args: any): any'.

ThisParameterType<T>

获取函数类型 T 的 this 类型。

function function toHex(this: Number): stringtoHex(this: Numberthis: Number) {
  return this.Number.toString(radix?: number | undefined): string
Returns a string representation of an object.
@paramradix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
toString
(16)
} function function numberToString(n: ThisParameterType<typeof toHex>): stringnumberToString(n: Numbern: type ThisParameterType<T> = T extends (this: infer U, ...args: never) => any ? U : unknown
Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter.
ThisParameterType
<typeof function toHex(this: Number): stringtoHex>) {
return function toHex(this: Number): stringtoHex.CallableFunction.apply<Number, string>(this: (this: Number) => string, thisArg: Number): string (+1 overload)
Calls the function with the specified object as the this value and the elements of specified array as the arguments.
@paramthisArg The object to be used as the this object.
apply
(n: Numbern)
}

OmitThisParameter<T>

从函数类型 T 中移除 this 类型。

function function toHex(this: Number): stringtoHex(this: Numberthis: Number) {
  return this.Number.toString(radix?: number | undefined): string
Returns a string representation of an object.
@paramradix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
toString
(16)
} const const fiveToHex: () => stringfiveToHex: type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T
Removes the 'this' parameter from a function type.
OmitThisParameter
<typeof function toHex(this: Number): stringtoHex> = function toHex(this: Number): stringtoHex.CallableFunction.bind<(this: Number) => string>(this: (this: Number) => string, thisArg: Number): () => string (+1 overload)
For a given function, creates a bound function that has the same body as the original function. The this object of the bound function is associated with the specified object, and has the specified initial parameters.
@paramthisArg The object to be used as the this object.
bind
(5)
var console: Consoleconsole.Console.log(...data: any[]): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log)
log
(const fiveToHex: () => stringfiveToHex())
//

ThisType<T>

获取函数类型 T 的 this 类型。

type type ObjectDescriptor<D, M> = {
    data?: D | undefined;
    methods?: (M & ThisType<D & M>) | undefined;
}ObjectDescriptor<function (type parameter) D in type ObjectDescriptor<D, M>D, function (type parameter) M in type ObjectDescriptor<D, M>M> = {
  data?: D | undefineddata?: function (type parameter) D in type ObjectDescriptor<D, M>D
  methods?: (M & ThisType<D & M>) | undefinedmethods?: function (type parameter) M in type ObjectDescriptor<D, M>M & interface ThisType<T>
Marker for contextual 'this' type
ThisType
<function (type parameter) D in type ObjectDescriptor<D, M>D & function (type parameter) M in type ObjectDescriptor<D, M>M> // Type of 'this' in methods is D & M
}; function function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MmakeObject<function (type parameter) D in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MD, function (type parameter) M in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MM>(desc: ObjectDescriptor<D, M>desc: type ObjectDescriptor<D, M> = { data?: D | undefined; methods?: (M & ThisType<D & M>) | undefined; }ObjectDescriptor<function (type parameter) D in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MD, function (type parameter) M in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MM>): function (type parameter) D in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MD & function (type parameter) M in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MM { let let data: objectdata: object = desc: ObjectDescriptor<D, M>desc.data?: D | undefineddata || {} let let methods: objectmethods: object = desc: ObjectDescriptor<D, M>desc.methods?: (M & ThisType<D & M>) | undefinedmethods || {} return { ...let data: objectdata, ...let methods: objectmethods } as function (type parameter) D in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MD & function (type parameter) M in makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & MM } let let obj: { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }obj = function makeObject<{ x: number; y: number; }, { moveBy(dx: number, dy: number): void; }>(desc: ObjectDescriptor<{ x: number; y: number; }, { moveBy(dx: number, dy: number): void; }>): { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }makeObject({ data?: { x: number; y: number; } | undefineddata: { x: numberx: 0, y: numbery: 0 }, methods?: ({ moveBy(dx: number, dy: number): void; } & ThisType<{ x: number; y: number; } & { moveBy(dx: number, dy: number): void; }>) | undefinedmethods: { function moveBy(dx: number, dy: number): voidmoveBy(dx: numberdx: number, dy: numberdy: number) { this.x: numberx += dx: numberdx // Strongly typed this this.y: numbery += dy: numberdy // Strongly typed this }, }, }) let obj: { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }obj.x: numberx = 10 let obj: { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }obj.y: numbery = 20 let obj: { x: number; y: number; } & { moveBy(dx: number, dy: number): void; }obj.function moveBy(dx: number, dy: number): voidmoveBy(5, 5) //

条件判定类型

条件类型是 TypeScript 中强大且灵活的类型构造方式,它允许根据类型关系进行条件判断生成不同的类型。 分布式条件类型是条件类型的一种特殊形式,它允许条件类型在联合类型上进行分发,以便更精确地推断和处理类型。

Conditional Types(条件类型)

条件类型基于输入的类型关系来确定最终的类型。它使用 infer 关键字来推断和定义类型。 条件类型通常结合了 TypeScript 中的 extends 关键字,这样就可以根据条件来确定最终的类型。

根据输入类型选择不同的类型

条件类型基于输入的类型关系来确定最终的类型。它使用 infer 关键字来推断和定义类型。 条件类型通常结合了 TypeScript 中的 extends 关键字,这样就可以根据条件来确定最终的类型。

示例:

type type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : "other"TypeName<function (type parameter) T in type TypeName<T>T> =
  function (type parameter) T in type TypeName<T>T extends string ? 'string' :
    function (type parameter) T in type TypeName<T>T extends number ? 'number' :
      function (type parameter) T in type TypeName<T>T extends boolean ? 'boolean' :
        'other';

type 
type A = "string"
A
= type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : "other"TypeName<string>
type
type B = "number"
B
= type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : "other"TypeName<number>
type
type C = "boolean"
C
= type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : "other"TypeName<boolean>
type
type D = "other"
D
= type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : "other"TypeName<object>
type
type E = "string" | "number"
E
= type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : "other"TypeName<string | number>
//

在这个例子中,TypeName<T> 条件类型根据传入的类型 T 来确定最终返回的类型字符串。如果 T 是 stringnumberboolean 类型,则返回对应的类型字符串,否则返回 'other'

条件类型中使用 infer 关键字

infer 关键字通常与extends结合使用,用于在条件类型内部声明一个类型变量,并从中提取或推断出一个类型。 它允许我们在泛型条件类型中推断出待推断类型的部分。

具体左右有以下两点:

  1. TypeScript 支持 infer 来提取类型的一部分,通过模式匹配的方式。

示例:

type type ExtractReturnType<T> = T extends (...args: any[]) => infer R ? R : neverExtractReturnType<function (type parameter) T in type ExtractReturnType<T>T> = function (type parameter) T in type ExtractReturnType<T>T extends (...args: any[]args: any[]) => infer function (type parameter) RR ? function (type parameter) RR : never

function function greet(): stringgreet(): string {
  return 'Hello!'
}

type 
type GreetReturnType = string
GreetReturnType
= type ExtractReturnType<T> = T extends (...args: any[]) => infer R ? R : neverExtractReturnType<typeof function greet(): stringgreet>
//

这个例子中的 ExtractReturnType<T> 条件类型获取函数类型 T 的返回类型。它使用了 infer 关键字来推断函数的返回类型,如果 T 是一个函数类型,则返回其返回类型,否则返回 never

  1. infer extends 用来做类型转换,比如 stringnumber、转 boolean 等;
enum enum CodeCode {
  function (enum member) Code.a = 111a = 111,
  function (enum member) Code.b = 222b = 222,
  function (enum member) Code.c = "ccc"c = 'ccc',
}

type type StrToNum<Str> = Str extends `${infer Num extends number}` ? Num : StrStrToNum<function (type parameter) Str in type StrToNum<Str>Str> =
  function (type parameter) Str in type StrToNum<Str>Str extends `${infer function (type parameter) NumNum extends number}`
    ? function (type parameter) NumNum
    : function (type parameter) Str in type StrToNum<Str>Str

type 
type res = "ccc" | 111 | 222
res
= type StrToNum<Str> = Str extends `${infer Num extends number}` ? Num : StrStrToNum<`${enum CodeCode}`>
//
  1. 条件类型配合泛型使用
type type Diff<T, U> = T extends U ? never : TDiff<function (type parameter) T in type Diff<T, U>T, function (type parameter) U in type Diff<T, U>U> = function (type parameter) T in type Diff<T, U>T extends function (type parameter) U in type Diff<T, U>U ? never : function (type parameter) T in type Diff<T, U>T

type type FilterOut<T, U> = T extends any ? Diff<T, U> : neverFilterOut<function (type parameter) T in type FilterOut<T, U>T, function (type parameter) U in type FilterOut<T, U>U> = function (type parameter) T in type FilterOut<T, U>T extends any ? type Diff<T, U> = T extends U ? never : TDiff<function (type parameter) T in type FilterOut<T, U>T, function (type parameter) U in type FilterOut<T, U>U> : never

type 
type Result = "b" | "d"
Result
= type FilterOut<T, U> = T extends any ? Diff<T, U> : neverFilterOut<'a' | 'b' | 'c' | 'd', 'a' | 'c'>
//

在这个例子中,FilterOut<T, U> 条件类型根据传入的两个联合类型 T 和 U,从 T 中过滤掉属于 U 类型的成员, 返回剩余的类型。通过 Diff<T, U> 辅助实现了这个操作。这种方式可以在处理类型时非常有用,比如过滤掉某些特定类型。

Distributive Conditional Types(分布式条件类型)

分布式条件类型是条件类型的一种特殊形式,它在联合类型上进行推断和分发,并返回联合类型中每个成员的条件类型。

type type ToArray<T> = T extends any ? T[] : neverToArray<function (type parameter) T in type ToArray<T>T> = function (type parameter) T in type ToArray<T>T extends any ? function (type parameter) T in type ToArray<T>T[] : never

type 
type StrArray = string[]
StrArray
= type ToArray<T> = T extends any ? T[] : neverToArray<string>
type
type NumArray = number[]
NumArray
= type ToArray<T> = T extends any ? T[] : neverToArray<number>
type
type UnionArray = string[] | number[]
UnionArray
= type ToArray<T> = T extends any ? T[] : neverToArray<string | number>
//

在这个例子中,ToArray<T> 条件类型以联合类型 T 为输入,并将其分发到联合类型的每个成员上,返回一个数组类型。 这种分布式行为使得条件类型在处理联合类型时更加灵活和强大。

条件类型和分布式条件类型为 TypeScript 中的类型系统增加了极大的灵活性和表达能力, 允许开发者根据复杂的类型关系来定义和推断类型。

Mapped Types(映射类型)

映射类型(Mapped Types) 是 TypeScript 中一种强大的类型操作,它允许你通过已有类型来创建新类型, 通常通过映射现有类型的属性、方法或者创建新的属性来实现。

常见的映射类型是利用 keyof 关键字配合索引类型来生成新的类型。一个经典的例子是 Partial<T> 类型。它接受一个类型 T 并将所有属性设置为可选的:

type type MyPartial<T> = { [P in keyof T]?: T[P] | undefined; }MyPartial<function (type parameter) T in type MyPartial<T>T> = {
  [function (type parameter) PP in keyof function (type parameter) T in type MyPartial<T>T]?: function (type parameter) T in type MyPartial<T>T[function (type parameter) PP]
}

interface User {
  User.name: stringname: string
  User.age: numberage: number
}

type 
type PartialUser = { name?: string | undefined; age?: number | undefined; }
PartialUser
= type MyPartial<T> = { [P in keyof T]?: T[P] | undefined; }MyPartial<User>
//

在这个例子中,Partial<T> 使用了映射类型,通过遍历 T 类型的所有属性(由 keyof T 获取), 创建了一个新类型,该类型包含了原类型 T 的所有属性,并将它们设为可选的。

除了 Partial,还有一些其他常见的映射类型:

  • Readonly<T>:将类型 T 中所有属性设置为只读。
  • Pick<T, K>:选择类型 T 中的特定属性 K。
  • Record<K, T>:根据键类型 K 创建一个新类型,其属性为类型 T。
  • Exclude<T, U>Extract<T, U>:从类型 T 中排除或提取符合类型 U 的部分。

映射类型可以使类型操作更加灵活,能够根据现有类型创建出符合特定需求的新类型。 这种功能特别适用于工具类型(Utility Types)的定义,使得类型系统更具表现力和可维护性。

Template Literal Types(模板文字类型)

Template Literal Types(模板文字类型)是 TypeScript 4.1 引入的一项新特性,它允许在类型系统中对字符串文本进行操作和转换。这项功能利用了模板字符串的灵活性,使得可以在类型声明中使用类似于模板字符串的语法。

在模板文字类型中,可以使用模板字符串的 ${} 语法来动态地创建字符串字面量类型。 这使得类型系统更具表现力,能够进行更复杂的字符串类型操作。

举个例子,假设有一个类型 WelcomeMessage,用于根据用户类型生成不同的欢迎消息:

type type User = "admin" | "user"User = 'admin' | 'user';

type type WelcomeMessage<T extends User> = `Welcome, ${Capitalize<T>}!`WelcomeMessage<function (type parameter) T in type WelcomeMessage<T extends User>T extends type User = "admin" | "user"User> = `Welcome, ${type Capitalize<S extends string> = intrinsic
Convert first character of string literal type to uppercase
Capitalize
<function (type parameter) T in type WelcomeMessage<T extends User>T>}!`
type
type AdminWelcome = "Welcome, Admin!"
AdminWelcome
= type WelcomeMessage<T extends User> = `Welcome, ${Capitalize<T>}!`WelcomeMessage<'admin'>
type
type UserWelcome = "Welcome, User!"
UserWelcome
= type WelcomeMessage<T extends User> = `Welcome, ${Capitalize<T>}!`WelcomeMessage<'user'>
//

在这个例子中,WelcomeMessage 是一个模板文字类型,利用了模板字符串中的 ${} 语法。 它动态地根据传入的用户类型("admin" 或 "user")生成相应的欢迎消息。 这里使用了 Capitalize<T> 来确保用户名的首字母大写。

模板文字类型在类型定义中能够进行字符串的拼接、转换等操作,使得在类型层面上能够更灵活地处理和操作字符串类型。

类型推断关键字

在 TypeScript 中,有几个关键字和操作符用于类型判定。 这些关键字和操作符帮助你在代码中进行类型检查、类型判断和类型转换。

typeof

typeof 是一个类型查询操作符,用于获取变量或表达式的类型。它可以返回该值的类型字符串表示。 比如 typeof variable 返回变量的类型,如 'number'、'string'、'object' 等。

const const numberVar: 10numberVar = 10

type 
type NumberType = 10
NumberType
= typeof const numberVar: 10numberVar
//

instanceof

instanceof 运算符用于检查对象是否是特定类的实例。它返回一个布尔值表示检查结果。

class Animal {}
class Dog extends Animal {}

const dog = new Dog()
if (dog instanceof Dog) {
  console.log('It is a dog!')
}

in

in 关键字用于检查对象是否具有特定属性。它在条件语句中常用于判断对象是否包含某个属性。

interface Person {
  name: string
  age: number
}

const person: Person = { name: 'Alice', age: 30 }
if ('age' in person) {
  console.log('Person has age property.')
}

type guards

类型守卫是自定义的函数或条件语句,用于在代码块内缩小变量的类型范围。 它们可以是 typeofinstanceof 或者其他自定义条件的组合。

function function isNumber(value: any): value is numberisNumber(value: anyvalue: any): value: anyvalue is number {
  return typeof value: anyvalue === 'number'
}

function function process(value: any): voidprocess(value: anyvalue: any) {
  if (function isNumber(value: any): value is numberisNumber(
value: any
value
)) {
// value 在此处被缩小为 number 类型 var console: Consoleconsole.Console.log(...data: any[]): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log)
log
(
value: number
value
.Number.toFixed(fractionDigits?: number | undefined): string
Returns a string representing a number in fixed-point notation.
@paramfractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
toFixed
(2))
} else { var console: Consoleconsole.Console.log(...data: any[]): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log)
log
('Value is not a number')
} }

as

as 关键字用于类型断言,允许将一个变量断言为特定的类型。

const someValue: any = 'hello'
const length = (someValue as string).length

这些关键字和操作符能够在 TypeScript 中进行类型判断、类型检查和类型转换,有助于确保代码的类型安全性和正确性。