Conditional Types
用处
条件类型可以帮助减少函数重载次数
interface IdLabel{
id: number
}
interface NameLabel{
name: string
}
type NameOrId <T extends number | string> = T extends number ? IdLabel : NameLabel
function createLabel<T extends number | string>(idOrName: T): NameOrId<T>{
throw "unimplemented"
}
let a = createLabel("ts")
let c = createLabel(Math.random(Math.random() ? "hello": 42)
Conditional Type Constraints
type MessageOf<T extends {message: unknown}> = T["message"]
interface Email{
message: string
}
// 类型 为string
type EmailMessageContents = MessageOf<Email>
在数组中的“现象”
type Flatten<T> = T extends any[] ? T[number] : T
// Str 为 string
type Str = Flatten<string[]>
// Num 为 number
type Num = Flatten<number>
在条件类型中使用 infer
type Flatten<T> = T extends Array<infer Item> ? Item : T
可以直接 infer 函数的返回值类型,Return
type GetReturnType<T> = T extends (...args: never[]) => infer Return : Return : never
// Num 为 number
type Num = GetReturnType<() => number>
// Bools 为 never
// 因为void 表示没有返回值,那么就推断不出返回值的类型,走到false分支,为never
type Bools = GetReturnType<(a: boolean, b:boolean) => void>
函数重载的情况下
declare function stringOrNum(x: string): string;
declare function stringOrNum(x: number): number;
declare function stringOrNum(x: string | number): string | number;
// T1 为string | number
// TS 会推导所有可能的返回值类型
type T1 = ReturnType<typeof stringOrNum>
分布式条件类型 Distributive Conditional Types
当泛型参数是联合类型的时候,就会出现分布式条件类型,如下
返回类型为 string[] | number[],这是因为 T 为 string | number
type ToArray<T> = T extends any ? T[] : never
// 类型为 string[] | number[]
type StrArrOrNumArr = ToArray<string | number>
那么有没有会自动方法让 返回类型为 (string | number)[] 呢?
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never
type StrOrNumArr = ToArrayNonDist<string | number>
Template Literal Types
排列组合
type EmailLocaleIDs = "welcome_email" | "email_heading"
type FooterLocaleIDs = "footer_title" | "footer_sendoff"
// "welcome_email_id" | "email_heading_id" | "footer_title_id" | "footer_sendoff_id"
type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`
String Unions in Types
type PropEventSource<T> = {
on(eventName: `${K extends string & Keyof T}Changed`, callback:(newValue: T[K]) => void):void
}
// 往返回值 T 类型上又联合了 PropEventSource<T> 类型
declare function makeWatchedObject<T>(obj: T): T & PropEventSource<T>
内在字符操作类型 ->Intrinsic String Manipulation Types
Uppercase/Lowercase/Capitalize/Uncapitalize 仅在编译过程中存在,d.ts文件中是不存在的
StringType 其实是 ---> S extends string