TypeScrip类型编程第一步:从索引类型到映射类型

学过java后学TS一天就感觉学会了,一看就会 一做就废。B站上的绝大部分TS还不如去看看文档 一点类型编程的进阶知识都没有。建议有编程基础的直接看文档。

看的b站视频感觉ts很简单,看了掘金小册的ts发现b站的视频只能学个定义。学到类型编程就发现晦涩难懂。第一眼会了,再仔细看看又不会了。那先从最简单的索引类型开始。

索引类型

索引类型:索引签名类型索引类型查询索引类型访问

索引签名类型

索引签名类型主要指的是在接口或类型别名中,通过以下语法来快速声明一个键值类型一致的类型结构

typescript 复制代码
interface MyObject {
  [key: string]: number;
}

const obj: MyObject = {
  a: 1,
  b: 2,
  c: 3,
};

//[]是索引类型访问 具体详情下面小节有
console.log(obj['a']); // 输出: 1  
console.log(obj['b']); // 输出: 2

定义了一个名为MyObject的接口,它具有一个索引签名类型,允许使用字符串作为索引,并且对应的值类型为数字。然后,我们创建了一个obj对象,可以通过字符串索引来访问其属性。

不同的属性名,定义不同的类型

typescript 复制代码
// 错误的尝试: TypeScript不允许这样做
interface MixedTypeDictionary {
  [key: string]: string;
  [key: number]: number; // Error: An index signature parameter type cannot be a union type
}

需要不同的属性具有不同的类型,你应该明确地在接口或类型别名中声明它们:

javascript 复制代码
interface StringOrBooleanTypes {
  propA: number;
  propB: boolean;
  [key: string]: number | boolean;
}

索引类型查询

将对象中的所有键转换为对应字面量类型,然后再组合成联合类型

typescript 复制代码
interface Foo {
  gsy: 1,
  599: 2
}

type FooKeys = keyof Foo; // "gsy" | 599

索引类型访问

通过 obj[expression] 的方式来访问属性

typescript 复制代码
interface Foo {
  propA: number;
  propB: boolean;
}

type PropAType = Foo['propA']; // number
type PropBType = Foo['propB']; // boolean

配合keyof

typescipt 复制代码
interface Foo {
  propA: number;
  propB: boolean;
  propC: string;
}

type PropTypeUnion = Foo[keyof Foo]; // string | number | boolean

在未声明索引签名类型的情况下,我们不能使用 NumberRecord[string] 这种原始类型的访问方式,而只能通过键名的字面量类型来进行访问。

ts 复制代码
interface Foo {
  propA: number;
}

// 类型"Foo"没有匹配的类型"string"的索引签名。
type PropAType = Foo[string]; 

★映射类型 ★

前置知识学完了,就到三合一了。

映射类型的主要作用即是基于键名映射到键值类型。放段小册的伪代码。

javascript 复制代码
type Stringify<T> = {
  [K in keyof T]: string;
};

//伪代码
const StringifiedFoo = {};
for (const k of Object.keys(Foo)){
  StringifiedFoo[k] = string;
}

xdm看了上面的代码 有点基础肯定学会了,我也学会了 但过会又忘了。还得再细点,来点正确的废话

我的废话

ts 复制代码
type Clone<T> = {
  [K in keyof T]: T[K];
};

这里的T[K]其实就是上面说到的索引类型访问,我们使用键的字面量类型访问到了键值的类型,这里就相当于克隆了一个接口。需要注意的是,这里其实只有K in 属于映射类型的语法,keyof T 属于 keyof 操作符,[K in keyof T][]属于索引签名类型,T[K]属于索引类型访问。

  • T 是一个将被克隆的类型变量。
  • [K in keyof T] 是一个索引类型查询和映射类型的结合。对于类型 T 中的每个属性键 K,都会创建一个相同键的属性。
  • T[K] 表示键 K 在原始类型 T 中对应的属性类型。
ts 复制代码
type User = {
  id: number;
  name: string;
  email: string;
};

type UserClone = Clone<User>;

定义了一个名为 User 的类型,它有三个属性:idname、和 email。当我们使用映射类型 [K in keyof T] 时,这里的 T 是指我们定义的 User 类型,keyof TUser 的所有属性键的联合类型,K 是这些键中的每一个。 对于 User 类型,keyof User 将得到所有属性名的联合类型

ts 复制代码
keyof User = "id" | "name" | "email";

每个 K 将相继地是这个联合类型的成员,即先是 "id",然后 "name",最后 "email"

对于 T[K],它表示类型 T 中键 K 对应的值的类型。在我们的例子中,User[K] 的可能值为以下类型:

  • 对于 K"id"User[K] 的类型是 number
  • 对于 K"name"User[K] 的类型是 string
  • 对于 K"email"User[K] 的类型是 string

Clone<User> 的上下文中,[K in keyof User]: User[K]; 将分别为每个属性创建一个同名的属性,并且保持对应的类型,如下所示:

  • id: number,因为 User["id"]number 类型。
  • name: string,因为 User["name"]string 类型。
  • email: string,因为 User["email"]string 类型。 因此,映射类型 [K in keyof T]: T[K]; 实际上遍历了 User 类型的每个属性,保留了每个属性的键和类型,并在新的 Clone<User> 类型中复制了这个结构。
相关推荐
郝晨妤17 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
红尘炼心1 天前
一个困扰我许久的TypeScript定义问题
前端·react.js·typescript
baiduguoyun1 天前
TypeScript 中的三斜杠指令语法
typescript
潘敬2 天前
flutter 语法糖库 flutter_magic 发布 1.0.1
开发语言·前端·javascript·flutter·typescript
高木的小天才2 天前
HarmonyOS一次开发多端部署三巨头之功能级一多开发和工程级一多开发
前端·华为·typescript·harmonyos
周三有雨3 天前
vue3 + vite 实现版本更新检查(检测到版本更新时提醒用户刷新页面)
前端·vue.js·typescript
清灵xmf5 天前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
Amd7945 天前
Nuxt.js 应用中的 prepare:types 事件钩子详解
typescript·自定义·配置·nuxt·构建·钩子·类型
王解6 天前
Jest项目实战(2): 项目开发与测试
前端·javascript·react.js·arcgis·typescript·单元测试
鸿蒙开天组●6 天前
鸿蒙进阶篇-网格布局 Grid/GridItem(二)
前端·华为·typescript·harmonyos·grid·mate70