前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >TS 从 0 到 1 - 泛型

TS 从 0 到 1 - 泛型

作者头像
Cellinlab
发布2023-05-17 19:56:24
发布2023-05-17 19:56:24
40600
代码可运行
举报
文章被收录于专栏:Cellinlab's BlogCellinlab's Blog
运行总次数:0
代码可运行

在 C# 和 Java 中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。

设计泛型的关键目的是在成员之间提供有意义的约束,这些成员可以是:类的实例成员、类的方法、函数参数、函数返回值。

泛型是允许同一个函数接受不同类型参数的一种模板。和 any 相比,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型。

# 泛型语法

代码语言:javascript
代码运行次数:0
复制
// <T> 用于传递类型
// 可以链式传递给参数类型和返回类型
function identity <T>(value: T): T {
  return value;
}

<T> 中的 T 称类型变量,是希望传递给 identity 函数的类型占位符,同时它被分配给 value 参数来代替它的类型。

T 代表 Type,在定义泛型时通常用作第一个类型变量名称。实际上 T 可以用任何有效名称代替。

  • K(Key):表示对象中的键类型
  • V(Value):表示对象中的值类型
  • E(Element):表示元素类型

不只能定义一个类型变量,可以引入希望定义的任何数量的类型变量。

代码语言:javascript
代码运行次数:0
复制
function identity <T, U>(value: T, message: U): T {
  console.log(message);
  return value;
}

console.log(identity<Number, string>(2022, 'cell'));

除了为类型变量显示设定值之外,更常见的是使编译器自动选择这些类型,从而使代码更简洁。

代码语言:javascript
代码运行次数:0
复制
function identity <T, U>(value: T, message: U): T {
  console.log(message);
  return value;
}

console.log(identity(2022, 'cell'));

# 泛型接口

代码语言:javascript
代码运行次数:0
复制
interface GenericIdentityFn<T> {
  (arg: T): T;
}

# 泛型类

代码语言:javascript
代码运行次数:0
复制
class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();

myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

# 泛型工具类型

# typeof

typeof 用来获取一个变量声明或对象的类型。

代码语言:javascript
代码运行次数:0
复制
interface Person {
  name: string;
  age: number;
}

const p: Person = {
  name: 'cell',
  age: 18,
};

type PersonType = typeof p; // Person

function toArray(x: number): Array<number> {
  return [x];
}

type Func = typeof toArray; // (x: number) => number[]

# keyof

keyof 用于获取某类型的所有键,其返回类型是联合类型。

代码语言:javascript
代码运行次数:0
复制
interface Person {
  name: string;
  age: number;
}

type K1 = keyof Person; // "name" | "age"
type K2 = keyof Person[]; // "length" | "push" | "pop" | "concat" | ...
type K3 = keyof { [x: string]: Person }; // string | number

在 TypeScript 中支持两种索引签名,数字索引和字符串索引:

代码语言:javascript
代码运行次数:0
复制
interface StringArray {
  [index: string]: string; // 字符串索引 keyof StringArray => string | number
}

interface StringArray1 {
  [index: number]: string; // 数字索引 keyof StringArray1 => number
}

为了同时支持两种索引类型,要求数字索引的返回值必须是字符串索引返回值的子类。原因是当使用数值索引时,JavaScript 在执行索引操作时,会先把数值索引先转换为字符串索引。所以,keyof { [x: string]: Person } 的结果会返回 string | number

# in

in 用来遍历枚举类型

代码语言:javascript
代码运行次数:0
复制
type Keys = "a" | "b" | "c";

type Obj = {
  [p in Keys]: any;
}; // { a: any, b: any, c: any }

# infer

在条件类型语句中,可以用 infer 声明一个类型变量并进行使用。

代码语言:javascript
代码运行次数:0
复制
type ReturnType<T> = T extends (
  ...args: any[]
) => infer R
  ? R
  : any;

# extends

可以使用 extends 添加泛型约束。

代码语言:javascript
代码运行次数:0
复制
interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

loggingIdentity(1); // Error because number doesn't have a .length property
loggingIdentity({ length: 10, value: 3 }); // OK

# Partial

Partial<T> 的作用就是将某个类型里的属性全部变为可选项 ?

代码语言:javascript
代码运行次数:0
复制
type Partial<T> = {
  [P in keyof T]?: T[P];
};

代码语言:javascript
代码运行次数:0
复制
interface Todo {
  title: string;
  description: string;
}

function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  return { ...todo, ...fieldsToUpdate };
}

const todo1 = {
  title: "Learn TypeScript",
  description: "study hard",
};

const todo2 = updateTodo(todo1, {
  description: "keep on studying",
});
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/5/7,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # 泛型语法
  • # 泛型接口
  • # 泛型类
  • # 泛型工具类型
    • # typeof
    • # keyof
    • # in
    • # infer
    • # extends
    • # Partial
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档