条件类型根据条件选择类型,类似于三元表达式。条件类型让类型系统更加灵活,可以根据输入类型动态确定输出类型。
条件类型使用 extends 关键字和三元表达式语法。
type IsString<T> = T extends string ? true : false
type A = IsString<string>
type B = IsString<number>
const a: A = true
const b: B = false
T extends string ? true : false 表示如果 T 是 string 的子类型,则类型是 true,否则是 false。
条件类型会分布式应用于联合类型。
type ToArray<T> = T extends any ? T[] : never
type StringOrNumberArray = ToArray<string | number>
const arr: StringOrNumberArray = ["hello"]
ToArray<string | number> 分布式应用,结果是 string[] | number[]。
使用元组可以禁止分布式行为。
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never
type Result = ToArrayNonDist<string | number>
const arr: Result = ["hello", 1]
[T] extends [any] 避免了分布式应用,结果是 (string | number)[]。
infer 关键字可以在条件类型中推断类型。
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any
function greet(name: string): string {
return `你好,${name}`
}
type GreetReturn = ReturnType<typeof greet>
const result: GreetReturn = "你好,张三"
infer R 推断函数的返回值类型,R 就是返回值类型。
使用 infer 提取数组的元素类型。
type ElementType<T> = T extends (infer E)[] ? E : never
type StringElement = ElementType<string[]>
type NumberElement = ElementType<number[]>
const str: StringElement = "hello"
const num: NumberElement = 123
infer E 推断数组的元素类型。
使用 infer 提取 Promise 的值类型。
type Awaited<T> = T extends Promise<infer U> ? U : T
type StringPromise = Awaited<Promise<string>>
type NumberValue = Awaited<number>
const str: StringPromise = "hello"
const num: NumberValue = 123
infer U 推断 Promise 的值类型。
使用 infer 提取函数的参数类型。
type Parameters<T> = T extends (...args: infer P) => any ? P : never
function greet(name: string, age: number): void {}
type GreetParams = Parameters<typeof greet>
const params: GreetParams = ["张三", 25]
infer P 推断函数的参数类型元组。
条件类型可以约束类型参数。
type Message<T extends { message: string }> = T["message"]
interface Success {
message: string
code: number
}
type SuccessMessage = Message<Success>
const msg: SuccessMessage = "操作成功"
T extends { message: string } 约束 T 必须有 message 属性。
条件类型可以嵌套使用。
type TypeName<T> =
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
T extends undefined ? "undefined" :
T extends Function ? "function" :
"object"
type T1 = TypeName<string>
type T2 = TypeName<number[]>
type T3 = TypeName<() => void>
const t1: T1 = "string"
const t2: T2 = "object"
const t3: T3 = "function"
嵌套条件类型可以处理多种情况。
条件类型在实际开发中常用于创建类型守卫函数。
type NonNullable<T> = T extends null | undefined ? never : T
function assertNotNull<T>(value: T): NonNullable<T> {
if (value === null || value === undefined) {
throw new Error("值不能为空")
}
return value as NonNullable<T>
}
const value: string | null = "hello"
const nonNull = assertNotNull(value)
console.log(nonNull.toUpperCase())
NonNullable<T> 排除了 null 和 undefined 类型。
条件类型根据条件选择类型,使用 extends 关键字和三元表达式语法。条件类型会分布式应用于联合类型。infer 关键字可以在条件类型中推断类型,常用于提取函数返回值、数组元素、Promise 值和函数参数类型。条件类型可以嵌套使用,处理多种情况。条件类型是创建灵活类型的重要工具。