当前位置: 首页 > news >正文

Typescript学习教程,从入门到精通,TypeScript 泛型与类型操作详解(二)(17)

TypeScript 泛型与类型操作详解(二)

本文将详细介绍 TypeScript 中的一些高级类型特性,包括条件类型、分布式条件类型、infer 关键字、内置工具类型、类型查询、类型断言、类型细化和类型守卫等。

1. 条件类型(Conditional Types)

1.1 定义

条件类型允许根据类型之间的关系在类型系统中进行条件判断。其语法类似于 JavaScript 中的三元运算符:

T extends U ? X : Y
  • 解释: 如果类型 T 可以赋值给类型 U,则结果类型为 X,否则为 Y

1.2 示例

type IsString<T> = T extends string ? true : false;type A = IsString<string>; // A 的类型为 true
type B = IsString<number>; // B 的类型为 false

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

当条件类型应用于联合类型时,TypeScript 会将联合类型中的每个成员单独应用于条件类型,这种行为称为“分布式”。

2.1 示例

type ToArray<T> = T extends any ? T[] : never;type A = ToArray<string | number>; // A 的类型为 string[] | number[]

在这个例子中,ToArray 条件类型被应用于 string | number,结果为 string[] | number[]

3. infer 关键字

infer 关键字用于在条件类型中推断类型。它通常用于提取类型的一部分,例如函数的返回类型或参数类型。

3.1 示例:提取函数返回类型

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;// 使用内置的 ReturnType
type Func = () => string;
type Result = ReturnType<Func>; // Result 的类型为 string

3.2 示例:提取数组元素类型

type ElementType<T> = T extends (infer E)[] ? E : T;type A = ElementType<string[]>; // A 的类型为 string
type B = ElementType<number>;   // B 的类型为 number

4. 内置工具类型(Utility Types)

TypeScript 提供了一些内置的工具类型,简化常见的类型操作。以下是一些常用的工具类型及其示例。

4.1 Partial<T>

将类型 T 的所有属性设为可选。

interface User {id: number;name: string;age?: number;
}type PartialUser = Partial<User>;
// PartialUser 等同于:
// {
//   id?: number;
//   name?: string;
//   age?: number;
// }

4.2 Required<T>

将类型 T 的所有属性设为必填。

type RequiredUser = Required<PartialUser>;
// RequiredUser 等同于:
// {
//   id: number;
//   name: string;
//   age: number;
// }

4.3 Readonly<T>

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

type ReadonlyUser = Readonly<User>;
// ReadonlyUser 等同于:
// {
//   readonly id: number;
//   readonly name: string;
//   readonly age?: number;
// }

4.4 Record<K, T>

构造一个对象类型,其键为 K,值为 T

type StringNumberMap = Record<string, number>;
// StringNumberMap 等同于:
// {
//   [key: string]: number;
// }type UserRoles = Record<'admin' | 'user', boolean>;
// UserRoles 等同于:
// {
//   admin: boolean;
//   user: boolean;
// }

4.5 Pick<T, K>

从类型 T 中选取一组属性 K 构成新类型。

type PickUser = Pick<User, 'id' | 'name'>;
// PickUser 等同于:
// {
//   id: number;
//   name: string;
// }

4.6 Omit<T, K>

从类型 T 中排除一组属性 K 构成新类型。

type OmitUser = Omit<User, 'age'>;
// OmitUser 等同于:
// {
//   id: number;
//   name: string;
// }

4.7 Exclude<T, U>

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

type ExcludeString = Exclude<string | number | boolean, string | number>;
// ExcludeString 的类型为 boolean

4.8 Extract<T, U>

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

type ExtractString = Extract<string | number | boolean, string>;
// ExtractString 的类型为 string

4.9 NonNullable<T>

从类型 T 中排除 nullundefined

type NonNullableUser = NonNullable<User | null | undefined>;
// NonNullableUser 的类型为 User

4.10 Parameters<T>

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

type Func = (a: string, b: number) => void;
type Params = Parameters<Func>;
// Params 的类型为 [string, number]

4.11 ConstructorParameters<T>

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

type SomeClass = new (a: string, b: number) => void;
type ConstructorParams = ConstructorParameters<SomeClass>;
// ConstructorParams 的类型为 [string, number]

4.12 ReturnType<T>

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

type Func = () => string;
type Return = ReturnType<Func>;
// Return 的类型为 string

4.13 InstanceType<T>

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

type SomeClass = new () => { id: number };
type Instance = InstanceType<SomeClass>;
// Instance 的类型为 { id: number }

4.14 ThisParameterType<T>

提取函数类型 Tthis 参数类型。

type FuncWithThis = (this: Date, x: string) => void;
type ThisParam = ThisParameterType<FuncWithThis>;
// ThisParam 的类型为 Date

4.15 OmitThisParameter<T>

移除函数类型 Tthis 参数类型。

type FuncWithoutThis = OmitThisParameter<FuncWithThis>;
// FuncWithoutThis 的类型为 (x: string) => void

4.16 ThisType<T>

用于在对象字面量中指定 this 的上下文类型。

type ObjectWithThis = {id: number;getId(this: ObjectWithThis): number;
};const obj: ObjectWithThis = {id: 1,getId(this: ObjectWithThis) {return this.id;}
};

5. 类型查询(Type Queries)

类型查询使用 typeof 操作符来获取变量或属性的类型。

5.1 示例

let age = 25;
type AgeType = typeof age; // AgeType 的类型为 numberconst user = {id: 1,name: 'Alice'
};
type UserType = typeof user;
// UserType 的类型为 { id: number; name: string }

6. 类型断言(Type Assertions)

类型断言允许开发者手动指定一个值的类型,绕过 TypeScript 的类型检查。

6.1 <T>类型断言

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

6.2 as T 类型断言

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

6.3 类型断言的约束

类型断言不能违反类型层级。例如,不能将 number 断言为 string

6.4 const 类型断言

const 断言用于创建只读、字面量类型的值。

let x = "hello" as const;
// x 的类型为 "hello"let y = { id: 1, name: "Alice" } as const;
// y 的类型为 { readonly id: 1; readonly name: "Alice" }

6.5 ! 类型断言

! 用于断言某个值不是 nullundefined

function getLength(s?: string) {return s!.length;
}

7. 类型细化(Type Narrowing)

类型细化是通过代码逻辑来缩小变量的类型范围,常用的方法包括类型守卫、赋值语句分析、控制流分析等。

7.1 类型守卫(Type Guards)

7.1.1 typeof 类型守卫
function printId(id: string | number) {if (typeof id === "string") {console.log(id.toUpperCase());} else {console.log(id.toFixed(2));}
}
7.1.2 instanceof 类型守卫
function printDate(date: Date | string) {if (date instanceof Date) {console.log(date.toUTCString());} else {console.log(date.toUpperCase());}
}
7.1.3 自定义类型守卫
interface Cat {meow(): void;
}interface Dog {bark(): void;
}function isCat(animal: Cat | Dog): animal is Cat {return (animal as Cat).meow !== undefined;
}function speak(animal: Cat | Dog) {if (isCat(animal)) {animal.meow();} else {animal.bark();}
}

7.2 赋值语句分析

通过赋值语句,TypeScript 可以推断出变量的更具体类型。

let x: string | number;
x = "hello";
// x 的类型被细化为 stringx = 123;
// x 的类型被细化为 number

7.3 基于控制流的类型分析

TypeScript 会根据控制流(如 ifelsereturn 等)来推断变量的类型。

function example(x: string | number) {if (typeof x === "string") {// x 的类型为 stringconsole.log(x.toUpperCase());} else {// x 的类型为 numberconsole.log(x.toFixed(2));}
}

7.4 断言函数(Assertion Functions)

断言函数用于在运行时验证类型,并在验证失败时抛出错误。

function assertIsString(val: any): asserts val is string {if (typeof val !== "string") {throw new Error("Value is not a string");}
}function printString(s: string | number) {assertIsString(s);console.log(s.toUpperCase());
}

8. 案例代码

8.1 使用 PartialPick 创建部分属性对象

interface User {id: number;name: string;age: number;email: string;
}function updateUser(user: User, updates: Partial<Pick<User, 'name' | 'email'>>) {return { ...user, ...updates };
}const alice: User = { id: 1, name: "Alice", age: 30, email: "alice@example.com" };
const updatedAlice = updateUser(alice, { name: "Alicia", email: "alicia@example.com" });
// updatedAlice 的类型为 User

8.2 使用 ExcludeExtract 进行类型操作

type Mixed = string | number | boolean | string[];type NonString = Exclude<Mixed, string>; // NonString 的类型为 number | boolean | string[]
type OnlyString = Extract<Mixed, string>;  // OnlyString 的类型为 stringtype NonEmptyString = Exclude<OnlyString, ''>; // NonEmptyString 的类型为 string

8.3 使用 ReturnType 获取函数返回类型

type GreetFunc = (name: string) => string;type GreetReturn = ReturnType<GreetFunc>; // GreetReturn 的类型为 stringfunction greet(name: string): GreetReturn {return `Hello, ${name}!`;
}

8.4 使用 Parameters 获取函数参数类型

type SumFunc = (a: number, b: number) => number;type SumParams = Parameters<SumFunc>; // SumParams 的类型为 [number, number]function sum(a: number, b: number): number {return a + b;
}const params: SumParams = [1, 2];

8.5 使用 ThisParameterTypeOmitThisParameter 处理 this 参数

type FuncWithThis = (this: Date, x: string) => void;type ThisParam = ThisParameterType<FuncWithThis>; // ThisParam 的类型为 Datetype FuncWithoutThis = OmitThisParameter<FuncWithThis>; // FuncWithoutThis 的类型为 (x: string) => voidfunction example(this: ThisParam, x: string) {console.log(this.toUTCString(), x);
}const date = new Date();
example.call(date, "hello");

8.6 使用 ThisType 在对象字面量中指定 this 类型

type ObjectWithThis = {id: number;getId(this: ObjectWithThis): number;
};const obj: ObjectWithThis = {id: 1,getId(this: ObjectWithThis) {return this.id;}
};console.log(obj.getId());

8.7 使用 is 进行自定义类型守卫

interface Cat {meow(): void;
}interface Dog {bark(): void;
}function isCat(animal: Cat | Dog): animal is Cat {return (animal as Cat).meow !== undefined;
}function speak(animal: Cat | Dog) {if (isCat(animal)) {animal.meow();} else {animal.bark();}
}const cat: Cat = { meow: () => console.log("Meow!") };
const dog: Dog = { bark: () => console.log("Woof!") };speak(cat); // 输出: Meow!
speak(dog); // 输出: Woof!

8.8 使用 const 断言创建只读对象

const config = {apiUrl: "https://api.example.com",timeout: 3000
} as const;type ConfigType = typeof config;
// ConfigType 的类型为:
// {
//   readonly apiUrl: "https://api.example.com";
//   readonly timeout: 3000;
// }

8.9 使用 NonNullable 排除 nullundefined

type MaybeString = string | null | undefined;type DefiniteString = NonNullable<MaybeString>; // DefiniteString 的类型为 stringfunction getString(): MaybeString {return "Hello";
}const str: DefiniteString = getString()!;

8.10 使用 InstanceType 获取构造函数实例类型

class Person {constructor(public name: string) {}
}type PersonConstructor = typeof Person;type PersonInstance = InstanceType<PersonConstructor>; // PersonInstance 的类型为 Personconst person: PersonInstance = new Person("Alice");

总结

TypeScript 提供了丰富的类型操作工具,使得开发者能够在编译阶段进行更严格的类型检查和更灵活的类型操作。通过理解和应用这些高级类型特性,可以显著提升代码的可维护性和可靠性。

相关文章:

  • Unity开发之Webgl自动更新程序包
  • 华为OD机试真题——矩形相交的面积(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
  • 线性代数入门:轻松理解二阶与三阶行列式的定义与理解
  • 【课堂笔记】EM算法
  • 华为OD机试真题——AI面板识别(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
  • Windows MongoDB C++驱动安装
  • JavaScript性能优化实战技术文章大纲
  • 【计算机网络】第2章:应用层—Web and HTTP
  • MySQL、PostgreSQL、Oracle 区别详解
  • 重新测试deepseek Jakarta EE 10编程能力
  • 2025LitCTF 复现
  • Java 对接 Office 365 邮箱全攻略:OAuth2 认证 + JDK8 兼容 + Spring Boot 集成(2025 版)
  • DEEPSEEK帮写的STM32消息流函数,直接可用.已经测试
  • PaddleOCR本地部署 (Python+Flask)
  • 【Linux 基础知识系列】第二篇-Linux 发行版概述
  • 代码随想录算法训练营 Day59 图论Ⅸ dijkstra优化版 bellman_ford
  • ADB识别手机系统弹授权框包含某段文字-并自动点击确定按钮
  • HTTP/HTTPS与SOCKS5三大代理IP协议,如何选择最佳协议?
  • Nginx详解(三):ngx_http_rewrite_module模块核心指令详解
  • python同步mysql数据
  • 如何用腾讯云主机做网站/三只松鼠搜索引擎营销案例
  • 七台河网站网站建设/南京百度推广开户
  • .flv 网站播放/成都网站推广公司
  • asp.net企业网站建设/推广策划方案范文
  • 如何实现wordpress伪静态/seo属于技术还是营销
  • 什么是响应网站设计/有什么平台可以发广告