TypeScript 类型体操之 Readonly & Tuple to Object

今天继续学 TypeScript 类型体操。按难度来的,学习下第7题 Readonly 和第11题 Tuple to Object。

7、Readonly

Readonly 的使用

Readonly 是 Typescript 提供的内置工具类型,Readonly<T>,用于将类型 T 中的所有属性设置为只读。

举个例子,如何使用 Readonly<T> 工具类型:

typescript 复制代码
interface Person {
  name: string;
  age: number;
}

const person: Readonly<Person> = {
  name: 'Alice',
  age: 25,
};

person.name = 'Bob'; // 编译错误,无法修改只读属性

console.log(person); // 输出: { name: 'Alice', age: 25 }

在上述示例中,我们使用 Readonly<Person> 工具类型将 Person 类型中的所有属性设置为只读。然后,我们创建了一个 person 对象,并尝试修改其 name 属性,但由于 person 是只读类型,所以会在编译时报错。

通过使用 Readonly<T> 工具类型,我们可以方便地将任何类型的属性设置为只读,提高代码的可靠性和安全性。

Readonly 的实现

1、首先在 TypeScript 中,可以使用 readonly 修饰符来指定一个只读属性。

typescript 复制代码
interface Person {
  readonly name: string;
  age: number;
}

const person: Person = {
  name: 'Alice',
  age: 25,
};

person.name = 'Bob'; // 编译错误,无法修改只读属性

console.log(person); // 输出: { name: 'Alice', age: 25 }

通过使用 readonly 修饰符,我们可以指定某个属性为只读,防止其被修改。

2、然后在 TypeScript 类型体操之 Pick 中我们已经学到了关键字 in 和 keyof。

在映射类型中,in 关键字用于遍历一个类型的属性名,并对每个属性进行相应的操作。
keyof 是 TypeScript 中的一个关键字,用于获取一个类型的所有属性名组成的联合类型。

现在可以很简单的实现 Readonly 了。

ts 复制代码
type MyReadonly<T> = {
  readonly [key in keyof T]: T[key]
}

11、Tuple to Object

这个个人认为是相对有点难度的题目。之前面试的时候被问到过,当时真的是一脸懵逼。T^T 然后就挂了。

传入一个元组类型,将这个元组类型转换为对象类型,这个对象类型的键/值都是从元组中遍历出来。

例如:

ts 复制代码
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const

type result = TupleToObject<typeof tuple> 
// { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}

1、什么是元组类型

元组类型是 TypeScript 中的一种特殊数据类型,它允许我们定义一个固定长度和固定类型顺序的数组。

在元组类型中,每个元素的类型可以是不同的。我们可以通过使用方括号 [] 来定义一个元组类型,并在方括号中指定每个元素的类型。

以下是一个示例代码,展示了如何定义和使用元组类型:

typescript 复制代码
let tuple: [string, number, boolean];

tuple = ['apple', 10, true]; // 合法赋值

tuple = [10, 'apple', true]; // 错误,元素类型不匹配

let name: string = tuple[0]; // 类型为 string
let age: number = tuple[1]; // 类型为 number
let isValid: boolean = tuple[2]; // 类型为 boolean

在上述示例中,我们定义了一个名为 tuple 的元组类型,其中包含三个元素,分别是 string、number 和 boolean 类型。然后,我们可以将符合元组类型定义的值赋给 tuple 变量。

注意,元组类型要求每个元素的类型和顺序都要与定义一致。如果赋值时不符合元组类型的定义,TypeScript 编译器会报错。

2、获取元组类型中所有元素的联合类型

我们可以通过 T[number] 表示元组类型 T 中的所有元素的联合类型。因为下标是 number 类型,而通过下标我们可以获取所有的元组元素,所以 T[number] 就可以获取所有的元素了。代码举例:

typescript 复制代码
type Tuple = [string, number, boolean];

type TupleElements = Tuple[number]; // 类型为 string | number | boolean

3、通过 in 来遍历联合类型

前面提到了

在映射类型中,in 关键字用于遍历一个类型的属性名,并对每个属性进行相应的操作。

我们通过 in 来遍历映射类型的属性时,需要遍历所有属性名组成的联合类型。

在之前获取映射类型的属性名组成的联合类型时,我们可以通过 keyof 获取,而对于元组类型,我们直接通过 T[number] 获取。

所以现在可以写出答案:

ts 复制代码
type TupleToObject<T extends readonly any[]> = {
  [key in T[number]]: key
}

但这个时候还是会报错,原因是对象的键只可能使 string,number 和 symbol 这三种类型,而 any 却超出了这个范围,所以简单修改一下即可。

ts 复制代码
type TupleToObject<T extends readonly (string | number | symbol)[]> = {
  [key in T[number]]: key
}

为什么要加 readonly

题目给定的代码中加了 readonly ,在这里加不加有什么区别呢?

ts 复制代码
type TupleToObject<T extends (string | number | symbol)[]> = {
  [key in T[number]]: key
}
const tuple = [1, '2', 3, '4']
type ObjectByTuple = TupleToObject<typeof tuple>
// type ObjectByTuple = {
//   [x: string]: string;
//   [x: number]: number;
// }

如果这里我们原始对象为非 const 的时候,我们可以看到得到的映射类型是下标类型对应值类型,但是和元组中具体的值无关。

而当我们尝试指定 const 和相对应的 readonly:

ts 复制代码
type TupleToObject<T extends readonly (string | number | symbol)[]> = {
  [key in T[number]]: key
}
const tuple = [1, '2', 3, '4'] as const
type ObjectByTuple = TupleToObject<typeof tuple>
// type ObjectByTuple = {
//     1: 1;
//     2: "2";
//     3: 3;
//     4: "4";
// }

我们可以看到,得到的映射类型是下标对应相对的值。

对比题目要求,可以知道我们需要的是下面这个解法。

相关推荐
默_笙29 分钟前
🍔 中间件不只是打日志:四个钩子、一次短路,和自带的工具
前端·javascript
程序员老赵1 小时前
Docker 部署 Dolibarr:轻松搭建开源 ERP/CRM 平台
运维·前端·后端
星禾元亨1 小时前
同一件事有三份资料,AI 该信哪一份?冲突判定、优先级链与处置流程
前端·人工智能
Dovis(誓平步青云)1 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
穆梓兰煊1 小时前
TS5.7 vs 裸JS:AI应用少3坑
前端
榆瓷2 小时前
闲着没事,我把 WebGPU 的样板代码封成了一个库
前端
136096757232 小时前
页面打不开不是 Nginx 的错
前端·后端
liangshanbo12152 小时前
高级前端面试题:package.json 常见字段
前端·json
CappuccinoRose3 小时前
输入事件进阶
前端·javascript·输入事件
liangshanbo12154 小时前
面试题:前端工程化中 Tree Shaking的原理是什么?
前端·treeshaking