类型体操刷题系列(六)—Readonly/Deep Readonly/Tuple union

399 阅读1分钟

highlight: an-old-hope theme: condensed-night-purple ---T

目的

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

ts 类型体操 github 我的解答

题目大纲

1. Medium Readonly 2. Medium Deep Readonly 3. Medium tuple union

01. Medium Readonly

题目要求

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

type cases = [
  Expect<Alike<MyReadonly2<Todo1>, Readonly<Todo1>>>,
  Expect<Alike<MyReadonly2<Todo1, 'title' | 'description'>, Expected>>,
  Expect<Alike<MyReadonly2<Todo2, 'title' | 'description'>, Expected>>,
]

interface Todo1 {
  title: string
  description?: string
  completed: boolean
}

interface Todo2 {
  readonly title: string
  description?: string
  completed: boolean
}

interface Expected {
  readonly title: string
  readonly description?: string
  completed: boolean
}

我的答案

type MyReadonly2<T, K extends keyof T = keyof T> = {
  readonly [key in K]: T[key];
} & {
  [key2 in MyExclude<keyof T, K>]: T[key2];
};

知识点

1. 在使用ts对象的mapped语法的时候可以参杂Exclude等关键字

2. Medium Deep Readonly

题目要求

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

type cases = [Expect<Equal<DeepReadonly2<X>, Expected>>];

type X = {
  a: () => 22;
  b: string;
  c: {
    d: boolean;
    e: {
      g: {
        h: {
          i: true;
          j: "string";
        };
        k: "hello";
      };
    };
  };
};

type Expected = {
  readonly a: () => 22;
  readonly b: string;
  readonly c: {
    readonly d: boolean;
    readonly e: {
      readonly g: {
        readonly h: {
          readonly i: true;
          readonly j: "string";
        };
        readonly k: "hello";
      };
    };
  };
};

我的解答

type Primitive = string | number | boolean;

type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends Primitive | Function
    ? T[K]
    : DeepReadonly<T[K]>;
};


type DeepReadonly2<T> = {
  readonly [K in keyof T]: keyof T[K] extends never ? T[K] : DeepReadonly2<T[K]>;
};

知识点

Q1:如何判断一个类型是一个对象?

A1:使用keyof T extends never来判断

3. Medium tuple union

题目要求

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

type cases = [
  Expect<Equal<TupleToUnion<[123, '456', true]>, 123 | '456' | true>>,
  Expect<Equal<TupleToUnion<[123]>, 123>>,
]

我的解答

type TupleToUnion<T extends any[]> = T extends (infer P)[] ? P : never;

知识点

1. 上述情况中,T extends (infer P)[]推断出来的就是一个泛型,而T extends infer P推断的是一个数组