TypeScript细碎知识点:T[number]、T['length'] 与 as const
🐹 一、T[number]、T['length']
T[number] 用来获取元组的元素类型联合
T['length'] 用来获取元组的元素类型个数
💡元组类型是另一种Array类型,它确切地知道它包含多少元素,以及在特定位置包含哪些类型。
type A = ['a', 'b', 'c'] type C = A['length'] // 3 type B = A[number] // "a" | "b" | "c"
对于数组来说
type A = boolean[] type C = A['length'] // number type B = A[number] // boolean
🤔:这里估计会有一个疑问,为什么数组这里的T['length']得到的是number, 而元祖中得到的却是‘3’ ?
数组:TypeScript 将数组视为一个可以动态增长或缩小的集合,因此 length 属性的类型是 number。
元组:TypeScript 将元组视为一个固定长度的集合,每个位置的类型和数量都是已知的,因此 length 属性的类型是一个具体的数字。
示例一:第一个元素
题目:实现一个通用First<T>,它接受一个数组T并返回它的第一个元素的类型。
type arr1 = ['a', 'b', 'c'] type arr2 = [3, 2, 1] type head1 = First<arr1> // expected to be 'a' type head2 = First<arr2> // expected to be 3
结果:
type First<T> = T extends any[] ? T[0] : never
示例二: 最后一个元素
题目:实现一个通用Last<T>,它接受一个数组 T 并返回其最后一个元素的类型。
type arr1 = ['a', 'b', 'c', 'd'] type arr2 = [3, 2, 1] type tail1 = Last<arr1> // expected to be 'c' type tail2 = Last<arr2> // expected to be 1
结果:
type Last<T> = T extends any[] ? [any,...T][T['length']] : never
示例三:出堆
题目:实现一个通用Pop<T>,它接受一个数组 T 并返回一个没有最后一个元素的数组。
type arr1 = ['a', 'b', 'c', 'd'] type arr2 = [3, 2, 1] type re1 = Pop<arr1> // expected to be ['a', 'b', 'c'] type re2 = Pop<arr2> // expected to be [3, 2]
结果:
type Pop<T extends any[]> = T extends [...infer U, infer P] ? U : never
🐹 二、as const
as const 是 TypeScript 中的一个用于修饰符,它可以被用来修改类型推断的行为。
🍀 当 as const 修饰符用在变量声明或表达式的类型上时,它会强制 TypeScript 将变量或表达式的类型视为不可变的(immutable)。这意味着,如果你尝试对变量或表达式进行修改,TypeScript 会报错。例如:
const foo = ['a', 'b'] as const; foo.push('c'); // TypeScript 会报错,因为 foo 类型被声明为不可变的 const bar = { x: 1, y: 2 } as const; bar.x = 3; // TypeScript 会报错,因为 bar 类型被声明为不可变的
🍀 as const 修饰符还可以用来修改对象字面量和数组字面量的类型推断。在这种情况下,as const 会强制 TypeScript 将对象字面量或数组字面量的类型推断为不可变的,即使没有显式地指定类型。例如:
const foo = ['a', 'b'] as const; // 等价于 const foo: ['a', 'b'] = ['a', 'b'] const bar = { x: 1, y: 2 } as const; // 等价于 const bar: { x: 1, y: 2 } = { x: 1, y: 2 }
在这两个例子中,TypeScript 会将 foo 和 bar 的类型推断为不可变的数组和对象,即使没有显式地指定类型。
😊 总结一下就是,当使用 const assert 时,ts做了以下几件事
-
该表达式中的任何文字类型都不应该被扩展(例如,不应该从“hello”变成字符串)
let a = 'hello' as const //等价于 let a: 'hello' = 'hello'
-
对象字面值获得只读属性
const bar = { x: 1, y: 2 } as const; // 等价于 const bar: { x: 1, y: 2 } = { x: 1, y: 2 }
-
数组字面值变成只读元组
const foo = ['a', 'b'] as const; // 等价于 const foo: ['a', 'b'] = ['a', 'b']
浙公网安备 33010602011771号