文章目录
- [TS 类型体操练习](#TS 类型体操练习)
-
- [Tuple to Union](#Tuple to Union)
- [Tuple to Object](#Tuple to Object)
- [First of Array](#First of Array)
- [Last of Array](#Last of Array)
- Pop
- [Length of Tuple](#Length of Tuple)
TS 类型体操练习
Tuple to Union
Implement a generic TupleToUnion<T>
which covers the values of a tuple to its values union.
TupleToUnion
的目标是将元组类型中的元素类型转换为联合类型。
type Arr = ['1', '2', '3']
type Test = TupleToUnion<Arr> // expected to be '1' | '2' | '3'
实现:
jsx
type TupleToUnion<T extends any[]> = T[number];
使用索引访问类型 T[number]
,它会返回元组 T
中所有元素的联合类型
因为元组的索引是数字类型,所以 T[number]
表示取出元组中所有位置的类型,然后将它们合并成一个联合类型。
Tuple to Object
Given an array, transform it into an object type and the key/value must be in the provided array
将一个元组类型转换为对象类型,这个对象类型的键/值和元组中的元素对应。
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type result = TupleToObject<typeof tuple> // expected { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
实现:
jsx
type TupleToObject<T extends readonly any[]> = {
[K in T[number]]: K
}
上一题说到,T[number]
可以返回元组T中所有元素的联合类型,拿到起所有类型后,使用in
进行遍历,就可以达到 Tuple to Object
效果
First of Array
Implement a generic First<T>
that takes an Array T
and returns its first element's type.
实现一个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
实现:
第一反应就是直接取索引为0的一个元素类型来实现, type First<T extends any[]> = T[0];
但当遇到Expect<Equal<First<[]>, never>>:
所以要考虑当数组为空时,是取不到第一个元素索引的
因此最终实现:
jsx
type First<T extends any[]> = T extends [] ? never : T[0];
Last of Array
Implement a generic Last<T>
that takes an Array T
and returns its last element.
实现一个Last<T>
泛型,它接受一个数组T
并返回其最后一个元素的类型。
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]
type tail1 = Last<arr1> // expected to be 'c'
type tail2 = Last<arr2> // expected to be 1
实现:
跟 First of Array
一样, 要进行空数组判断,如果是空数组,就返回 never 类型, 表示永远不会发生;使用剩余运算,infer
推断最后一个元素之前的所有元素,保留最后一个元素推断 last
,如果满足非空数组,则返回最后一个元素类型。
jsx
type Last<T extends any[]> = T extends [...infer _, infer last] ? last : never;
Pop
Implement a generic Pop<T>
that takes an Array T
and returns an Array without it's last element.
实现一个泛型Pop<T>
,它接受一个数组T
,并返回一个由数组T
的前 N-1 项(N 为数组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]
这里的case要求:
所以我们不能将空数组,直接返回never,而是返回[]类型
实现:
jsx
type Pop<T extends any[]> = T extends [...infer remain, infer last]
? remain
: [];
Length of Tuple
For given a tuple, you need create a generic Length
, pick the length of the tuple
创建一个Length
泛型,这个泛型接受一个只读的元组,返回这个元组的长度。
type tesla = ['tesla', 'model 3', 'model X', 'model Y']
type spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']
type teslaLength = Length<tesla> // expected 4
type spaceXLength = Length<spaceX> // expected 5
实现:
在 TypeScript 中,数组是具有 length
属性的对象,该属性表示其长度, 所以可以直接这样获取元组的长度:
jsx
type Length<T extends any[]> = T["length"];
当我们调用 Length<typeof tesla>
时,typeof tesla
是一个只读数组。我们无法将只读数组分配给 any[]
类型,因此我们需要进一步限制 T
仅允许只读数组: