高级类型
TypeScript提供了强大的类型系统,包括高级类型操作和类型编程能力。
交叉类型
基本交叉类型
typescript
1// 交叉类型2interface Person {3 name: string;4 age: number;5}67interface Employee {8 id: number;9 department: string;10}1112type PersonEmployee = Person & Employee;1314const person: PersonEmployee = {15 name: "John",16 age: 30,17 id: 1,18 department: "Engineering"19};函数交叉类型
typescript
1// 函数交叉类型2type Function1 = (x: number) => number;3type Function2 = (x: string) => string;45type CombinedFunction = Function1 & Function2;67// 注意:这种交叉类型在实际使用中可能没有意义8// 因为一个函数不能同时接受number和string参数联合类型
基本联合类型
typescript
1// 联合类型2type StringOrNumber = string | number;34function processValue(value: StringOrNumber): string {5 if (typeof value === "string") {6 return value.toUpperCase();7 } else {8 return value.toString();9 }10}1112// 联合类型数组13type StringOrNumberArray = (string | number)[];1415const mixedArray: StringOrNumberArray = ["hello", 42, "world", 100];字面量联合类型
typescript
1// 字面量联合类型2type Status = "pending" | "success" | "error";34function handleStatus(status: Status): string {5 switch (status) {6 case "pending":7 return "Processing...";8 case "success":9 return "Completed successfully";10 case "error":11 return "An error occurred";12 }13}1415// 数字字面量联合类型16type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;1718function rollDice(): DiceRoll {19 return Math.floor(Math.random() * 6) + 1 as DiceRoll;20}类型守卫
typeof类型守卫
typescript
1// typeof类型守卫2function processValue(value: string | number): string {3 if (typeof value === "string") {4 return value.toUpperCase();5 } else {6 return value.toString();7 }8}910// 更复杂的typeof守卫11function formatValue(value: string | number | boolean): string {12 if (typeof value === "string") {13 return value.toUpperCase();14 } else if (typeof value === "number") {15 return value.toFixed(2);16 } else {17 return value ? "true" : "false";18 }19}instanceof类型守卫
typescript
1// instanceof类型守卫2class Animal {3 name: string;4 constructor(name: string) {5 this.name = name;6 }7}89class Dog extends Animal {10 bark(): string {11 return "Woof!";12 }13}1415class Cat extends Animal {16 meow(): string {17 return "Meow!";18 }19}2021function makeSound(animal: Animal): string {22 if (animal instanceof Dog) {23 return animal.bark();24 } else if (animal instanceof Cat) {25 return animal.meow();26 } else {27 return "Unknown animal sound";28 }29}自定义类型守卫
typescript
1// 自定义类型守卫2interface Bird {3 fly(): void;4 layEggs(): void;5}67interface Fish {8 swim(): void;9 layEggs(): void;10}1112function isFish(pet: Fish | Bird): pet is Fish {13 return (pet as Fish).swim !== undefined;14}1516function move(pet: Fish | Bird) {17 if (isFish(pet)) {18 pet.swim();19 } else {20 pet.fly();21 }22}2324// 使用in操作符的类型守卫25function move2(pet: Fish | Bird) {26 if ("swim" in pet) {27 pet.swim();28 } else {29 pet.fly();30 }31}条件类型
基本条件类型
typescript
1// 条件类型2type NonNullable<T> = T extends null | undefined ? never : T;34// 使用条件类型5type T0 = NonNullable<string | number | null>; // string | number6type T1 = NonNullable<string[] | null | undefined>; // string[]78// 条件类型与联合类型9type Diff<T, U> = T extends U ? never : T;10type Filter<T, U> = T extends U ? T : never;1112type T2 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"13type T3 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"分布式条件类型
typescript
1// 分布式条件类型2type ToArray<T> = T extends any ? T[] : never;34type T4 = ToArray<string | number>; // string[] | number[]56// 非分布式条件类型7type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;89type T5 = ToArrayNonDist<string | number>; // (string | number)[]条件类型推断
typescript
1// 条件类型推断2type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;34// 使用ReturnType5function getUser() {6 return { name: "John", age: 30 };7}89type User = ReturnType<typeof getUser>; // { name: string; age: number; }1011// 更复杂的条件类型推断12type FirstIfString<T> = T extends [infer S, ...unknown[]]13 ? S extends string14 ? S15 : never16 : never;1718type T6 = FirstIfString<[string, number, boolean]>; // string19type T7 = FirstIfString<[number, string, boolean]>; // never映射类型
基本映射类型
typescript
1// 基本映射类型2type Readonly<T> = {3 readonly [P in keyof T]: T[P];4};56type Partial<T> = {7 [P in keyof T]?: T[P];8};910type Required<T> = {11 [P in keyof T]-?: T[P];12};1314// 使用映射类型15interface User {16 id: number;17 name: string;18 email?: string;19}2021type ReadonlyUser = Readonly<User>;22type PartialUser = Partial<User>;23type RequiredUser = Required<User>;键重映射
typescript
1// 键重映射2type Getters<T> = {3 [P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];4};56type UserGetters = Getters<User>;7// 等价于:8// {9// getId: () => number;10// getName: () => string;11// getEmail: () => string | undefined;12// }1314// 过滤键15type RemoveKindField<T> = {16 [P in keyof T as Exclude<P, "kind">]: T[P];17};1819interface Circle {20 kind: "circle";21 radius: number;22}2324type KindlessCircle = RemoveKindField<Circle>; // { radius: number; }条件映射类型
typescript
1// 条件映射类型2type EventConfig<T extends string> = {3 [K in T]: { event: K; data: any };4};56type UserEvents = "click" | "hover" | "submit";7type UserEventConfig = EventConfig<UserEvents>;89// 等价于:10// {11// click: { event: "click"; data: any };12// hover: { event: "hover"; data: any };13// submit: { event: "submit"; data: any };14// }模板字面量类型
基本模板字面量类型
typescript
1// 模板字面量类型2type EmailLocaleIDs = "welcome_email" | "email_heading";3type FooterLocaleIDs = "footer_title" | "footer_sendoff";45type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`;67// 等价于:8// "welcome_email_id" | "email_heading_id" | "footer_title_id" | "footer_sendoff_id"910// 模板字面量类型推断11type PropEventSource<T> = {12 on(eventName: `${string & keyof T}Changed`, callback: (newValue: any) => void): void;13};1415declare function makeWatchedObject<T>(obj: T): T & PropEventSource<T>;1617const person = makeWatchedObject({18 firstName: "Saoirse",19 lastName: "Ronan",20 age: 2621});2223person.on("firstNameChanged", (newValue) => {24 console.log(`firstName was changed to ${newValue}!`);25});模板字面量类型操作
typescript
1// 模板字面量类型操作2type Uppercase<S extends string> = intrinsic;3type Lowercase<S extends string> = intrinsic;4type Capitalize<S extends string> = intrinsic;5type Uncapitalize<S extends string> = intrinsic;67// 使用这些内置类型8type T8 = Uppercase<"hello">; // "HELLO"9type T9 = Lowercase<"WORLD">; // "world"10type T10 = Capitalize<"hello">; // "Hello"11type T11 = Uncapitalize<"Hello">; // "hello"实用工具类型
内置工具类型
typescript
1// Partial<T>2interface Todo {3 title: string;4 description: string;5}67type PartialTodo = Partial<Todo>;8// 等价于:9// {10// title?: string;11// description?: string;12// }1314// Required<T>15type RequiredTodo = Required<Todo>;16// 等价于:17// {18// title: string;19// description: string;20// }2122// Readonly<T>23type ReadonlyTodo = Readonly<Todo>;24// 等价于:25// {26// readonly title: string;27// readonly description: string;28// }2930// Pick<T, K>31type TodoPreview = Pick<Todo, "title">;32// 等价于:33// {34// title: string;35// }3637// Omit<T, K>38type TodoInfo = Omit<Todo, "completed" | "createdAt">;39// 等价于:40// {41// title: string;42// description: string;43// }条件工具类型
typescript
1// Exclude<T, U>2type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"3type T1 = Exclude<string | number | (() => void), Function>; // string | number45// Extract<T, U>6type T2 = Extract<"a" | "b" | "c", "a" | "f">; // "a"7type T3 = Extract<string | number | (() => void), Function>; // () => void89// NonNullable<T>10type T4 = NonNullable<string | number | null | undefined>; // string | number1112// ReturnType<T>13type T5 = ReturnType<() => string>; // string14type T6 = ReturnType<(s: string) => void>; // void15type T7 = ReturnType<<T>() => T>; // unknown1617// InstanceType<T>18class C {19 x = 0;20 y = 0;21}2223type T8 = InstanceType<typeof C>; // C24type T9 = InstanceType<any>; // any25type T10 = InstanceType<never>; // never高级工具类型
typescript
1// ThisType<T>2interface ObjectDescriptor<D, M> {3 data?: D;4 methods?: M & ThisType<D & M>;5}67declare function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M;89let obj = makeObject({10 data: { x: 0, y: 0 },11 methods: {12 moveBy(dx: number, dy: number) {13 this.x += dx; // 强类型化14 this.y += dy; // 强类型化15 }16 }17});1819// ThisParameterType<T>20function toHex(this: Number) {21 return this.toString(16);22}2324type T11 = ThisParameterType<typeof toHex>; // Number2526// OmitThisParameter<T>27type T12 = OmitThisParameter<typeof toHex>; // () => string类型推断
类型推断基础
typescript
1// 类型推断2let x = 3; // 推断为 number3let y = "hello"; // 推断为 string4let z = [1, 2, 3]; // 推断为 number[]56// 上下文类型推断7window.onmousedown = function(mouseEvent) {8 console.log(mouseEvent.button); // 正确9};1011// 最佳公共类型推断12let x2 = [0, 1, null]; // 推断为 (number | null)[]13let x3 = [0, 1, null, "hello"]; // 推断为 (number | null | string)[]类型推断和泛型
typescript
1// 泛型类型推断2function identity<T>(arg: T): T {3 return arg;4}56let output = identity("myString"); // 推断为 string7let output2 = identity(123); // 推断为 number89// 约束类型推断10function getProperty<T, K extends keyof T>(obj: T, key: K) {11 return obj[key]; // 推断返回类型为 T[K]12}1314let x = { a: 1, b: 2, c: 3, d: 4 };15getProperty(x, "a"); // 推断为 number16getProperty(x, "m"); // 错误!类型编程
递归类型
typescript
1// 递归类型2type JsonValue = 3 | string4 | number5 | boolean6 | null7 | JsonValue[]8 | { [key: string]: JsonValue };910// 递归条件类型11type DeepReadonly<T> = {12 readonly [P in keyof T]: T[P] extends object13 ? T[P] extends Function14 ? T[P]15 : DeepReadonly<T[P]>16 : T[P];17};1819interface NestedObject {20 a: number;21 b: {22 c: string;23 d: {24 e: boolean;25 };26 };27}2829type DeepReadonlyNested = DeepReadonly<NestedObject>;类型级编程
typescript
1// 类型级编程 - 数字运算2type Length<T extends readonly any[]> = T["length"];34type T13 = Length<[1, 2, 3]>; // 356// 类型级编程 - 字符串操作7type StringLength<S extends string> = S extends `${infer First}${infer Rest}`8 ? StringLength<Rest> extends infer Length9 ? Length extends number10 ? [First, ...(Length extends 0 ? [] : [Length])]11 : never12 : never13 : [];1415type T14 = StringLength<"hello">; // ["h", "e", "l", "l", "o"]1617// 类型级编程 - 条件逻辑18type If<C extends boolean, T, F> = C extends true ? T : F;1920type T15 = If<true, "yes", "no">; // "yes"21type T16 = If<false, "yes", "no">; // "no"
评论