一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
题目
- First —— 获取数组的第一个元素的类型
- Length —— 获取元组的长度
首先,我想说的是,在这个栏目里的任何一个题目,只要你愿意都能在TS Playground中进行练习。
First 题目描述:
链接在这,实现一个通用First<T>,它接受一个数组T并返回它的第一个元素的类型。
/* _____________ 你的代码 _____________ */
type First<T extends any[]> = any //未完成
/* _____________ 测试用例 _____________ */
import { Equal, Expect } from '@type-challenges/utils'
type cases = [ // 这里有四个测试用例
Expect<Equal<First<[3, 2, 1]>, 3>>,
Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
Expect<Equal<First<[]>, never>>,
Expect<Equal<First<[undefined]>, undefined>>
]
type errors = [ // 这里是出错的情况
// @ts-expect-error
First<'notArray'>,
// @ts-expect-error
First<{ 0: 'arrayLike' }>
]
可以首先在链接中尝试,如果不行再查看以下线索:
tips
- 首先思考,T有什么特征?或者说,这题的T是什么类型,这个类型有什么特征?
- 如何表达这个特征?是否需要判断?
如果这里的线索还是不够你进行解题,可以尝试以下线索的答案,再次在链接中尝试。
第一点线索的答案是,T是一个数组泛型,也就是说T首先是一个数组,而数组在JavaScript中是一个对象,这个对象具有一个关键属性:length。
第二点线索的答案是,表达一个具有length属性的对象可以使用对象字面量的形式,是否需要判断这个问题,你可以查看测试用例的第三个和第四个,你会发现有空数组以及元素是undefined的情况。
综上所述,你应该让你的泛型数组去判断一下它自身的长度,如果自身长度为0,就按照第三个测试用例,返回never,否则的话就返回T[0]
验证
尝试在刚刚的链接中验证最终答案。
type First<T extends any[]> = T extends {length: 0} ? never : T[0]
Length 题目描述:
链接在这
,创建一个通用的Length,接受一个readonly的数组,返回这个数组的长度。
/* _____________ 你的代码 _____________ */
type Length<T extends any> = any //未完成
/* _____________ 测试用例 _____________ */
import { Equal, Expect } from '@type-challenges/utils'
const tesla = ['tesla', 'model 3', 'model X', 'model Y'] as const
const spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'] as const
type cases = [
Expect<Equal<Length<typeof tesla>, 4>>,
Expect<Equal<Length<typeof spaceX>, 5>>,
// @ts-expect-error
Length<5>,
// @ts-expect-error
Length<'hello world'>,
]
可以在上述链接中尝试解题,线索在下方:
tips
其实这里只有一个提示,并且跟First的题目是一样的,就是元组中如何取到length属性,只要取到length属性那么这题就结束了,额外一点提示是这里的元组是泛型T,如何约束一个泛型是一个readonly的元组?
由于这题比较简单,所以就直接上解题思路了。
- 泛型T如何约束为一个元组,元组是什么呢,
元组是元素类型有顺序的数组,而readonly的数组是会把里面的元素全部转为readonly类型的,比如type color = readonly ['red','green','blue']。那么如果有一个变量类型是color的第一个项,那类型将是字符串字面量类型'red'。所以如果你添加了readonly,那么这个数组就会成为一个元组。 - 获取元组的属性length,你可以使用T['length'],这里的T是一个数组对象,当你要拿到对象中的属性时,可以考虑使用索引映射类型,再看下面一个例子来尝试理解如何获取。
type person = {age: number, name: string}
//使用索引映射类型获取age的类型
type personAge = person['age'] //此时personAge 类型为 number
验证
尝试在刚刚的链接中验证最终答案。
type Length<T extends readonly any[]> = T['length']