ts-challenge 记录一

238 阅读3分钟

实现 Pick

00004-easy-pick

TS 提供了多个用于实现类型转换的 Utility Types。其中Pick<Type, Keys> 用来实现从 Type 中挑选出属性集 Keys (字符串字面量或数值字面量的联合类型),进而构建新类型。示例为:

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}
 
type TodoPreview = Pick<Todo, "title" | "completed">;
 
const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};
 
todo;
  ^
// const todo: TodoPreview

由题可知,K 的类型应为 字面量类型结合的联合类型;并且该字面量来自于接口 T 的键。因此需要 extends 进行类型约束,K extends keyof T 表示 K 被约束在 T 的 key 中。

题解如下:

type MyPick<T, K extends keyof T> = { [key in K]: T[key] }

相关知识点有:

  • type:类型别名,可指代任一类型的名字。语法为
type Point = {
    x: number;
    y: number
}
  • keyof:接受一个对象类型作为参数,并且基于它的键生成一个由字符串字面量或数值字面量组成的联合类型。
interface Point {
    x: number;
    y: number;
}

// 相当于:
// type keys = "x" | "y"
type keys = keyof Point;

实现 Readonly

00007-easy-readonly

Readonly<Type> 会构建出一个将 Type 的所有属性设置为只读属性的类型。示例为:

interface Todo {
  title: string;
}
 
const todo: Readonly<Todo> = {
  title: "Delete inactive users",
};
 
todo.title = "Hello";
       ^
// Cannot assign to 'title' because it is a read-only property.

我们可以通过 keyof T 拿到 T 的所有属性名,然后用 in 进行遍历,并将值赋值给K。最后 T[K] 取得对应属性的值时,将其设置为 readonly。对应题解如下:

type MyReadonly<T> = { readonly [K in keyof T]: T[K] }

Tuple to Object

00011-easy-tuple-to-object

由题目可知,我们需要从数组中获取所有值,并将其作为新对象中的键和值。首先什么是元组?

元组是一种特殊的 Array 类型,它的元素数量以及每个元素对应的类型都是确定的,各元素的类型不必相同。

type StringNumberPair = [string, number];

如上所示,StringNumberPair 描述的数组为,下标为 0 的位置包含了一个 string 类型的值,下标为 1 的位置包含了一个 number 类型的值。

由于元组可以确切知道包含多少个元素,因此我们可以通过检查 length 以获得具体的元素个数。

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] as const;

type DigitsLength = (typeof digits)['length']     // 10

该题涉及到的知识点有:

  • as const 表示 const 断言,此时数组类型变成 readonly,所以 TupleToObject 里也要加 readonly。
  • 通过 k in T[number] 实现遍历数组

然后,将下面的代码进行提交:

type TupleToObject<T extends readonly any[]> = { [K in T[number]] : K}

但会发现,有个地方标注了红色波浪线:

截屏2022-10-09 下午9.52.01.png 这是 @ts-expect-error 提示我们去修改 TupleToObject 的泛型限制。因为对象的 key 只能是 number、string 和 symbol 类型,修改后的题解为:

type TupleToObject<T extends readonly (number | string | symbol)[]> = { 
    [K in T[number]] : K
}

First of Array

00014-easy-first

通过测试用例可以看出,当我们传入的是一个数组时才会返回第一个元素,并且空数组时返回 never 类型。never 类型是什么呢?

never 类型表示从来不会被看到的值。当返回值是 never 类型的时候,意味着函数抛出了一个异常,或者终止了程序的执行。

题解如下:

type First<T extends any[]> = T extends [] ? never : T[0]

其中 extends 用于条件类型判断,当 extends 左边的类型可以赋值给右边的类型时,最终得到的就是第一个分支的类型。

SomeType extends OtherType ? TrueType : FalseType;