type-challenges/First & Length - easy

248 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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

  1. 首先思考,T有什么特征?或者说,这题的T是什么类型,这个类型有什么特征?
  2. 如何表达这个特征?是否需要判断?

如果这里的线索还是不够你进行解题,可以尝试以下线索的答案,再次在链接中尝试。

第一点线索的答案是,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']