TypeScript 之 Indexed Access Types

简介: TypeScript 的官方文档早已更新,但我能找到的中文文档都还停留在比较老的版本。所以对其中新增以及修订较多的一些章节进行了翻译整理。

4.png


前言


TypeScript 的官方文档早已更新,但我能找到的中文文档都还停留在比较老的版本。所以对其中新增以及修订较多的一些章节进行了翻译整理。


本篇整理自 TypeScript Handbook 中 「Indexed Access Types」 章节。


本文并不严格按照原文翻译,对部分内容也做了解释补充。


正文


我们可以使用 索引访问类型(indexed access type) 查找另外一个类型上的特定属性:


type Person = { age: number; name: string; alive: boolean };
type Age = Person["age"];
// type Age = number
复制代码


因为索引名本身就是一个类型,所以我们也可以使用联合、keyof 或者其他类型:


type I1 = Person["age" | "name"];  
// type I1 = string | number
type I2 = Person[keyof Person];
// type I2 = string | number | boolean
type AliveOrName = "alive" | "name";
type I3 = Person[AliveOrName];  
// type I3 = string | boolean
复制代码


如果你尝试查找一个不存在的属性,TypeScript 会报错:


type I1 = Person["alve"];
// Property 'alve' does not exist on type 'Person'.
复制代码


接下来是另外一个示例,我们使用 number 来获取数组元素的类型。结合 typeof 可以方便的捕获数组字面量的元素类型:


const MyArray = [
  { name: "Alice", age: 15 },
  { name: "Bob", age: 23 },
  { name: "Eve", age: 38 },
];
type Person = typeof MyArray[number];
// type Person = {
//    name: string;
//    age: number;
// }
type Age = typeof MyArray[number]["age"];  
// type Age = number
// Or
type Age2 = Person["age"];   
// type Age2 = number
复制代码


作为索引的只能是类型,这意味着你不能使用 const 创建一个变量引用:


const key = "age";
type Age = Person[key];
// Type 'key' cannot be used as an index type.
// 'key' refers to a value, but is being used as a type here. Did you mean 'typeof key'?
复制代码


然而你可以使用类型别名实现类似的重构:


type key = "age";
type Age = Person[key];
复制代码


最后讲一个实战案例:


假设有这样一个业务场景,一个页面要用在不同的 APP 里,比如淘宝、天猫、支付宝,根据所在 APP 的不同,调用的底层 API 会不同,我们可能会这样写:


const APP = ['TaoBao', 'Tmall', 'Alipay'];
function getPhoto(app: string) {
  // ...
}
getPhoto('TaoBao'); // ok
getPhoto('whatever'); // ok
复制代码


如果我们仅仅是对 app 约束为 string 类型,即使传入其他的字符串,也不会导致报错,我们可以使用字面量联合类型约束一下:


const APP = ['TaoBao', 'Tmall', 'Alipay'];
type app = 'TaoBao' | 'Tmall' | 'Alipay';
function getPhoto(app: app) {
  // ...
}
getPhoto('TaoBao'); // ok
getPhoto('whatever'); // not ok
复制代码


但写两遍又有些冗余,我们怎么根据一个数组获取它的所有值的字符串联合类型呢?我们就可以结合上一篇的 typeof 和本节的内容实现:


const APP = ['TaoBao', 'Tmall', 'Alipay'] as const;
type app = typeof APP[number];
// type app = "TaoBao" | "Tmall" | "Alipay"
function getPhoto(app: app) {
  // ...
}
getPhoto('TaoBao'); // ok
getPhoto('whatever'); // not ok
复制代码


我们来一步步解析:


首先是使用 as const 将数组变为 readonly 的元组类型:


const APP = ['TaoBao', 'Tmall', 'Alipay'] as const;
// const APP: readonly ["TaoBao", "Tmall", "Alipay"]
复制代码


但此时 APP 还是一个值,我们通过 typeof 获取 APP 的类型:


type typeOfAPP = typeof APP;
// type typeOfAPP = readonly ["TaoBao", "Tmall", "Alipay"]
复制代码


最后在通过索引访问类型,获取字符串联合类型:


type app = typeof APP[number];
// type app = "TaoBao" | "Tmall" | "Alipay"
复制代码


TypeScript 系列


TypeScript 系列文章由官方文档翻译、重难点解析、实战技巧三个部分组成,涵盖入门、进阶、实战,旨在为你提供一个系统学习 TS 的教程,全系列预计 40 篇左右。点此浏览全系列文章,并建议顺便收藏站点。


微信:「mqyqingfeng」,加我进冴羽唯一的读者群。


如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。



目录
相关文章
|
JavaScript 开发者 索引
搞懂 TypeScript 中的映射类型(Mapped Types)
搞懂 TypeScript 中的映射类型(Mapped Types)
755 0
|
JavaScript 前端开发 测试技术
TypeScript高级类型:探索Mapped Types的威力及衍生
TypeScript高级类型:探索Mapped Types的威力及衍生
「TypeScript」你必须要知道的 TS 高级技能点 —— Utility Types
「TypeScript」你必须要知道的 TS 高级技能点 —— Utility Types
|
JavaScript 安全
TypeScript 中你不一定知道的 top types,在用 any 之前先试试 unknown?
最近发现了一本 TS 相关的电子书,Tackling TypeScript[1]。随便翻看了一下,就发现了自己很感兴趣的一个问题,并且也经常听说在国内面试中出现。
|
JavaScript 开发者 索引
搞懂 TypeScript 中的映射类型(Mapped Types)
本文从数学中的映射作为切入点,详细介绍 TypeScript 映射类型(Mapped Type)并介绍映射类型的应用和修饰符的应用。
397 1
|
JavaScript 前端开发 API
TypeScript 之 Conditional Types
TypeScript 的官方文档早已更新,但我能找到的中文文档都还停留在比较老的版本。所以对其中新增以及修订较多的一些章节进行了翻译整理。
143 0
TypeScript 之 Conditional Types
|
JavaScript 前端开发 安全
TypeScript 之 Object Types
TypeScript 的官方文档早已更新,但我能找到的中文文档都还停留在比较老的版本。所以对其中新增以及修订较多的一些章节进行了翻译整理。
121 0
TypeScript 之 Object Types
|
JavaScript 前端开发 C++
TypeScript Basic Types(基本类型)
在学习TypeScript之前,我们需要先知道怎么才能让TypeScript写的东西正确的运行起来。有两种方式:使用Visual studio 和使用 NodeJs。 这里我选择的是NodeJs来编译TypeScript,因为我笔记本上的VS是2012的,在TypeScript的官网看到下载是TypeScript for VS2013和TypeScript for VS2015。
1158 0
|
1月前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
45 0
|
1月前
|
JavaScript 前端开发 开发者
深入理解TypeScript:类型系统与实用技巧
【10月更文挑战第8天】深入理解TypeScript:类型系统与实用技巧