逐一攻破TypeScript: Const 断言
前言
懂得as const的意义,懂得 Const 断言的使用,就能轻松实现用数组/对象的键/值创建联合类型,
即以下实现:
const arr = ['a', 'b', 'c'] // => type arrValue = 'a' | 'b' | 'c'
const obj = { 'a': 1, 'b': 2, } // => type objKey = 'a' | 'b'; type objValue = 1 | 2
预备知识
- typeof获取变量类型
- keyof索引类型查询
const obj = { a: 1, b: 2 }
type objType = typeof obj // { a: number, b: number }
type keys = keyof objType // 'a' | 'b'
基础知识
官方解释 TypeScript 3.4 引入了一种新的字面量结构,称为*
const*断言。它的语法是一个类型断言,const代替了类型名称(例如'hello' as const)。当我们用断言构造新的文字表达式时const,我们可以向语言发出信号
- 不应扩大该表达式中的文字类型(例如,不要从
"hello"到string)- 对象字面量获取
readonly属性- 数组文字变成
readonly元组
简而言之,使用const断言的变量,内部属性都是只读的,所以对象或数组的值都会被定义为字面量。
基础考察
1. 用数组的值创建联合类型
使用const断言与否,效果差异如下:
const arr = ['a', 'b', 'c'] // string[]
const arr1 = ['a', 'b', 'c'] as const // readonly ['a','b','c']
type arrValue = typeof arr[number] // string
type arrValue1 = typeof arr1[number] // 'a' | 'b' | 'c'
2. 用对象的键名创建联合类型
3. 用对象的键值创建联合类型
const obj = {
'a': 1,
'b': 2,
} as const
// 等价于
// const obj: {
// readonly a: 1;
// readonly b: 2;
// }
type objKey = keyof typeof obj // 'a' | 'b'
type objValue = typeof obj[keyof typeof obj] // 1 | 2
进阶考察
1. 用对象数组的键名创建联合类型
2. 用对象数组的键值创建联合类型
3. 用对象数组的指定键值创建联合类型
const objArr = [{
'a': 1,
'b': 2
}, {
'a': 3,
'b': 4,
}] as const
// 等价于
// const objArr: readonly [{
// readonly a: 1;
// readonly b: 2;
// }, {
// readonly a: 3;
// readonly b: 4;
// }]
type arrValues = typeof objArr[number] // {readonly a: 1,readonly b: 2} | {readonly a: 3,readonly b: 4}
type keys = keyof typeof objArr[number] // a | b
type values = typeof objArr[number][keys] // 1 | 3 | 2 | 4
type keyValues = typeof objArr[number]['a'] // 1 | 3
自我考察
- 已知
METHODS_MAP,如何实现正确实现request('/api',METHODS_MAP.GET)
const METHODS_MAP = { GET: 'GET',POST: 'POST'}
// => 实现
const request = (url: string, method: 'GET' | 'POST') => ({ url, method })
request('/api',METHODS_MAP.GET) // warn:类型“string”的参数不能赋给类型“"GET" | "POST"”的参数。
- 实现
const METHODS_MAP = { GET: 'GET', POST: 'POST' } as const
// =>
const request = (url: string, method: keyof typeof METHODS_MAP) => ({ url, method })
request('/api', METHODS_MAP.GET)
为什么需要对常量METHODS_MAP进行Const断言呢?因为TypeScript 并没有针对类型做进一步的推断,从而因此保证了类型的灵活性。
const METHODS_MAP = { GET: 'GET', POST: 'POST'} // { GET: string, POST: string}
const METHODS_MAP = { GET: 'GET', POST: 'POST' } as const // { GET: 'GET' as const , POST: 'POST' as const }
总结
- const断言允许我们编写更少的类型声明。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情