类型体操刷题系列(一)——Pick/ReadOnly/TupleObject

214 阅读1分钟

目的

Github上的类型体操,让你写出更加优雅的TS类型定义,以及探寻TS中我们不熟悉的只是,让我们开始TS的类型挑战把~2022希望通过更文的方式来督促自己学习,每日三题,坚持日更不断~~

ts 类型体操 github 我的解答

题目大纲

  1. Easy Pick
  2. Easy ReadOnly
  3. Easy Tuple Object

01. Easy Pick

题目要求

import { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Expected1, MyPick<Todo, 'title'>>>,
  Expect<Equal<Expected2, MyPick<Todo, 'title' | 'completed'>>>,
  // @ts-expect-error
  MyPick<Todo, 'title' | 'completed' | 'invalid'>,
]

interface Todo {
  title: string
  description: string
  completed: boolean
}

interface Expected1 {
  title: string
}

interface Expected2 {
  title: string
  completed: boolean
}

我的答案

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

知识点

A1. 如果获取对象 Key 的类型?

Q1. *使用keyof关键字

A2. 如何遍历对象?

Q2 ts mapping 的用法,使用 in关键字,其作用的是从多个类型中获取其中的一个类型(遍历对象keyof拿到的值,使用in关键字)

// 比如 A 的定义是如下所示
type A = "a" | "b" | "c";

// 获取类型为 'a', 'b'. 'c'的写法就是mapping
interface IAObject {
  [P in A]: P;
}

2. easy readOnly

题目要求

import { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<MyReadOnly<Todo1>, Readonly<Todo1>>>,
]

interface Todo1 {
  title: string
  description: string
  completed: boolean
  meta: {
    author: string
  }
}

我的解答

type MyReadOnly<T> = {
  readonly [P in keyof T]: T[P];
};

知识点

只需要将 key 前面加上readonly关键字,这个变量就变成了只读。

3. Easy Tuple Object

题目要求

完成从数组到对象的映射关系

import { Equal, Expect } from "@type-challenges/utils";

const tuple = ["tesla", "model 3", "model X", "model Y"] as const;

type cases = [
  Expect<
    Equal<
      TupleToObject<typeof tuple>,
      {
        tesla: "tesla";
        "model 3": "model 3";
        "model X": "model X";
        "model Y": "model Y";
      }
    >
  >
];

type error = TupleToObject<[[1, 2], {}]>;

我的解答

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

知识点

A1. 如何遍历数组中的每个元素?

Q1: 当T extends any[]的时候,使用T[number]