TypeScript学习(七):Handbook -> Conditional Types & Template Literal Types

665 阅读1分钟

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

参考

www.typescriptlang.org/docs/handbo…