typescript泛型

我们平常是对值编程,而泛型是对类型编程

一、初识泛型

1.1 keyof

可以用来取得一个对象接口的所有 key 值

interface Foo {
  name: string;
  age: number;
}

type FooKeys = keyof Foo; // 'name' | 'age'

1.2 in

in 则可以遍历枚举类型

type Keys = "a" | "b";

type obj = {
  [p in Keys]: number;
};

let a: obj = {
  a: 1,
  b: 2,
};

1.3 infer

infer 这个关键字, 在条件类型语句中, 我们可以用 infer 声明一个类型变量并且对它进行使用

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

function add(params: string) {
  return params;
}

type returnType = ReturnType<typeof add>;

infer R 就是声明一个变量来承载传入函数签名的返回值类型, 简单说就是用它取到函数返回值的类型方便之后使用.

1.4 Partial

Partial 作用是将传入的属性变为可选项.

源码:

type Partial<T> = { [P in keyof T]?: T[P] };

示例:

interface Person {
  name: string;
  sex: number;
  age: number;
}

type newP = Partial<Person>;

// type newP = {
//     name?: string;
//     sex?: number;
//     age?: number;
// }

1.5 Required

Required 的作用是将传入的属性变为必选项

源码:

type Required<T> = { [P in keyof T]-?: T[P] };

示例:

interface Person {
  name?: string;
  sex?: number;
  age?: number;
}

type newP = Required<Person>;

// type newP = {
//     name: string;
//     sex: number;
//     age: number;
// }

1.6 Readonly

将传入的属性变为只读选项

源码:

type Readonly<T> = { readonly [P in keyof T]: T[P] };

示例:

interface Person {
  name: string;
  sex?: number;
  age?: number;
}

type newP = Readonly<Person>;

// type newP = {
//     readonly name: string;
//     readonly sex?: number;
//     readonly age?: number;
// }

1.7 Record

将 K 中所有的属性的值转化为 T 类型

源码:

type Record<K extends keyof any, T> = { [P in K]: T };

示例:

interface PageInfo {
  title: string;
}

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};

1.8 Pick

从 T 中取出 一系列 K 的属性

源码:

type Pick<T, K extends keyof T> = { [P in K]: T[P] };

示例:

interface Person {
  name: string;
  age: number;
  visiable: boolean;
}
type Person1 = Pick<Person, "name" | "age">;

1.9 extends

条件类型

type TypeName<T> = T extends string
  ? "string"
  : T extends number
  ? "number"
  : T extends boolean
  ? "boolean"
  : T extends undefined
  ? "undefined"
  : T extends Function
  ? "function"
  : "object";

var a: TypeName<string> = "string";

1.10 Exclude

 提取出 T 不包含在 U 中的元素

源码:

type Exclude<T, U> = T extends U ? never : T

示例:

type A = number | string | boolean;
type B = number | boolean;

type newFoo = Exclude<A, B>;
// 相当于
// type Foo = string;

1.11 Extract

 Extract 的作用是提取出 T 包含在 U 中的元素

源码:

type Extract<T, U> = T extends U ? T : never;

示例:

type A = number | string | boolean
type B = number | boolean

type Foo = Extract<A, B>
// 相当于
type Foo = number | boolean

1.12 Omit

生成一个新类型,该类型拥有 T 中除了 K 属性以外的所有属性

源码:

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>> 

示例:

type Foo = {
	name: string
	age: number
}

type Bar = Omit<Foo, 'age'>
// 相当于
type Bar = {
	name: string
}

二、类型

2.1 联合类型

满足其中之一的类型就可以了。

interface NAS {
  host: string;
  port: number;
}

interface OSS {
  key: string;
  secret: string;
  port: number;
}

type MyStorage = NAS | OSS;

const storage: MyStorage = { host: "127.0.0.1", port: 80 };

2.2 交叉类型

满足所有的情况

interface NAS {
  host: string;
  port: number;
}

interface OSS {
  key: string;
  secret: string;
  port: number;
}

type MyStorage = NAS & OSS;

const storage: MyStorage = { host: "127.0.0.1", port: 80, key: "", secret: "" };

2.3 条件类型

interface NAS {
  host: string;
  port: number;
}

interface OSS {
  key: string;
  secret: string;
  port: number;
}

enum StorageType {
  NAS,
  OSS,
}

type MyStorage<T> = T extends StorageType.NAS
  ? NAS
  : T extends StorageType.OSS
  ? OSS
  : never;

const myStorage: MyStorage<StorageType.NAS> = {
  host: "",
  port: 0,
};

三、应用

3.1. 交集

        交集的定义:对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。

type Intersection<T, U> = Pick<
  T,
  Extract<keyof T, keyof U> & Extract<keyof U, keyof T>
>;

interface NAS {
  host: string;
  port: number;
}

interface OSS {
  key: string;
  secret: string;
  port: number;
}

type JiaoJi = Intersection<NAS, OSS>;

3.2. 差集

差集的定义:对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。

type Diff<T extends object, U extends object> = Pick<
  T,
  Exclude<keyof T, keyof U>
>;
type C1 = { name: string; age: number; visible: boolean };
type C2 = { name: string; age: number; sex: number };
type C11 = Diff<C1, C2>;

// type C11 = {
//     visible: boolean;
// }

3.3. 并集

对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。

type C1 = { name: string; age: number; visible: boolean };
type C2 = { name: string; age: number; sex: number };


type Compute<A extends any> = A extends Function ? A : { [K in keyof A]: A[K] };
type Merge<O1 extends object, O2 extends object> = Compute< O1 & Omit<O2, keyof O1>>;
type C1C2 = Merge<C1, C2>;

// type C1C2 = {
//     name: string;
//     age: number;
//     visible: boolean;
//     sex: number;
// }

覆盖并集

type C1 = { name: string; age: number; visible: boolean };
type C2 = { name: string; age: string; sex: number };

type Intersection<T, U> = Pick<
  T,
  Extract<keyof T, keyof U> & Extract<keyof U, keyof T>
>;
type Diff<T extends object, U extends object> = Pick<
  T,
  Exclude<keyof T, keyof U>
>;
type Overwrite<
  T extends object,
  U extends object,
  I = Diff<T, U> & Intersection<U, T>
> = Pick<I, keyof I>;
type overwrite = Overwrite<C1, C2>;

// type overwrite = {
//     name: string;
//     age: string;
//     visible: boolean;
// }

附录

参考连接:

https://www.typescriptlang.org/docs/handbook/utility-types.html

https://zhuanlan.zhihu.com/p/40311981

https://baijiahao.baidu.com/s?id=1717228098181547699&wfr=spider&for=pc

https://blog.youkuaiyun.com/azl397985856/article/details/106913210/

<think>我们根据用户需求,结合站内引用资料,系统整理TypeScript的相关信息。 注意:由于引用标记在用户输入中已明确(如[^1]),我们在回答中直接使用这些引用标记。 用户需求:了解TypeScript的介绍、使用方法及相关知识。 回答结构: 1. 简介(定义、目的) 2. 为什么需要(解决的问题) 3. 的使用方法(函数、接口、类) 4. 约束(限制的类范围) 5. 参数默认类 6. 常见应用场景 注意:使用中文回答,按照系统指令要求正确使用行内公式(虽然这个主题可能较少涉及数学公式,但如果有表达式如类参数等,可以用$...$表示)和独立公式(如果有的话)。 但根据内容,可能较少涉及数学公式,因此主要关注代码示例和文字描述。 同时,在回答末尾生成相关问题。 </think>### TypeScript详解 #### 一、介绍 (Generics)是TypeScript的核心特性,允许在定义函数、接口或类时不预先指定具体类,而是在使用时动态指定类。这种**参数化类**机制通过`<T>`语法实现,其中`T`是类变量(可自定义名称)。的主要价值在于: 1. **代码复用**:编写可适用于多种类的通用组件[^3] 2. **类安全**:编译器在编译阶段进行类检查,避免运行时错误[^3] 3. **灵活性**:保持类约束的同时支持不同类操作[^4] #### 二、基本使用方法 ##### 1. 函数 ```typescript function identity<T>(arg: T): T { return arg; } // 显式指定类 let output1 = identity<string>("Hello"); // string类 // 类推断 let output2 = identity(42); // number类(自动推断) ``` ##### 2. 接口 ```typescript interface KeyValuePair<K, V> { key: K; value: V; } // 使用 const pair: KeyValuePair<number, string> = { key: 1, value: "Apple" }; ``` ##### 3. 类 ```typescript class GenericQueue<T> { private data: T[] = []; push(item: T) { this.data.push(item); } pop(): T | undefined { return this.data.shift(); } } // 使用 const stringQueue = new GenericQueue<string>(); stringQueue.push("A"); stringQueue.push("B"); ``` #### 三、高级特性 1. **约束**:限制类参数的范围 ```typescript interface Lengthwise { length: number; } function logLength<T extends Lengthwise>(arg: T): void { console.log(arg.length); } logLength("text"); // 4 logLength([1, 2, 3]); // 3 ``` 2. **默认类参数** ```typescript function createArray<T = string>(length: number, value: T): T[] { return Array(length).fill(value); } createArray(3, "x"); // string[] createArray<number>(3, 5); // number[] ``` 3. **多类参数** ```typescript function swap<T, U>(tuple: [T, U]): [U, T] { return [tuple[1], tuple[0]]; } swap([7, "seven"]); // 返回 ["seven", 7] ``` #### 四、应用场景 1. **集合操作**:数组、栈、队列等数据结构的通用实现 2. **API响应处理**:统一处理不同类API返回的数据结构 3. **工具函数**:如`map`/`filter`等可复用高阶函数 4. **状态管理**:Redux的Action/Reducer类定义 5. **React组件**:通用组件Props的类约束 #### 五、最佳实践 1. 优先使用单字母类参数(`T`/`U`/`K`/`V`) 2. 当类关系复杂时,使用`extends`添加约束 3. 避免过度化,保持类可读性 4. 利用类推断减少显式类声明 > 通过TypeScript在保持JavaScript灵活性的同时,提供了强类语言的可靠性和工具支持,大幅提升大项目的可维护性[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值