Typescript - as const 详细介绍
1,引入
在介绍 as const
之前,得先介绍点其他的,以便更好的理解。
1.1,只读
在 Typescript 中,readonly
表示只读,可以在 interface
和 type
中标记属性
举例:对象
type Foo = {
readonly name: string;
readonly want: string;
};
const foo: Foo = { name: '下雪天的夏风', want: '求关注' };
// 报错:无法分配到 "name" ,因为它是只读属性。ts(2540)
foo.name = 456;
举例:数组
const arr: readonly string[] = ["a", "b", "c"];
// 报错:类型“readonly string[]”上不存在属性“push”。ts(2339)
arr.push('d')
// 报错:类型“readonly string[]”中的索引签名仅允许读取。ts(2542)
arr[1]= 'r'
readonly string[]
和ReadonlyArray<string>
是等价的。
1.2,元组
在 JavaScript
中,数组的元素可以是任意类型。而在 Typescript
中,如果数组的元素类型不一致,此时这个数组称为元祖(Tuple)。
元祖类型:元素数量和类型都确定的数组。
可以理解为:既然能确定每个元素的类型,那数量也就确定了。
let x: [string, number];
x = ['hello', 10]; // ok
x = [10, 'hello']; // Error
在元祖中,不能访问越界元素,但可以通过push
等方法扩展,但扩展元素的类型会使用联合类型替代。
x[0] = '你好' // ok
// 报错:长度为 "2" 的元组类型 "[string, number]" 在索引 "2" 处没有元素。ts(2493)
x[2] = 'xx'
// 报错:类型“boolean”的参数不能赋给类型“string | number”的参数。ts(2345)
x.push(true)
x.push('world') // ok
1.3,只读的元祖
下面的2种写法,因为只读的原因,二者在使用上并没有区别,都不能通过索引和方法修改。
但
Typescript
编译是会区分:数组类型和元素类型的,下面的例子中会有介绍。
// 只读数组
const list: readonly string[] = ['a', 'b']
// 只读元祖
const list: readonly [string, string] = ['a', 'b']
as const
就是在只读的元祖类型上再次提高精度:类型精确到值。
所以,
as const
得到是一个只读的元祖类型!
2,as const
2.1,需求
对于上面的list
来说,获取的数组元素的类型是string
// string
type tList = typeof list[number]
实际工作中,会遇到这样的需求:“要求某个变量的取值范围,限制某个数组范围内。”
以上面定义的 list
为例,需要一个这样的type
type tList = 'a' | 'b'
function getItem(item: tList) {}
2.2,as const 的效果
而 as const
就可以实现这个需求。我们对比下,注意listB
的类型
// 只读元祖
const listA: readonly [string, string] = ['a', 'b']
// listB 的类型是:readonly ["a", "b"]
const listB = ['a', 'b'] as const
// string
type tListA = typeof listA[number]
// 'a' | 'b'
type tListB = typeof listB[number]
typeof listA[number]
的读取顺序:typeof listA
再[number]
2.3,as const 的其他使用例子
1,数组解构
const arr = ['abc', 123]
const [p, q] = arr
// Property 'toUpperCase' does not exist on type 'string | number'.
// Property 'toUpperCase' does not exist on type 'number'.ts(2339)
p.toUpperCase()
可以看到,当我们能确定 p
是string
类型时,还是会报错。
解决办法就是as const
const arr = ['abc', 123] as const
2,扩展参数(展开语法)
在 Typescript
中,使用扩展参数时有2点要求,满足之一即可。
- 扩展参数必须具有元组类型
- 扩展参数需要传递给剩余参数
举例
const args = [1, 2];
function testArgs(a: number, b: number) {}
// 报错:扩展参数必须具有元组类型或传递给剩余参数.ts(2556)
testArgs(...args)
解决方法1
// 扩展参数必须具有元组类型
const args: [number, number] = [1, 2];
// 注意,这不是元祖类型!所以依旧会报错
const args: number[] = [1, 2];
而这个元祖类型也可以用as const
来解决
const args = [1, 2] as const;
解决方法2
// 扩展参数需要传递给剩余参数
function testArgs(...theArgs: number[]) {}
以上,如果对你有帮助,还请点个关注支持下。