类型体操刷题系列(十三)— AnyOf/isNever/isUnion

306 阅读1分钟

目的

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

ts 类型体操 github 我的解答

题目大纲

  1. Medium AnyOf
  2. Medium isNever
  3. Medium isUnion

01. Medium AnyOf

题目要求

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

type cases = [
  Expect<Equal<AnyOf<[1, 'test', true, [1], {name: 'test'}, {1: 'test'}]>, true>>,
  Expect<Equal<AnyOf<[1, '', false, [], {}]>, true>>,
  Expect<Equal<AnyOf<[0, 'test', false, [], {}]>, true>>,
  Expect<Equal<AnyOf<[0, '', true, [], {}]>, true>>,
  Expect<Equal<AnyOf<[0, '', false, [1], {}]>, true>>,
  Expect<Equal<AnyOf<[0, '', false, [], {name: 'test'}]>, true>>,
  Expect<Equal<AnyOf<[0, '', false, [], {1: 'test'}]>, true>>,
  Expect<Equal<AnyOf<[0, '', false, [], {name: 'test'}, {1: 'test'}]>, true>>,
  Expect<Equal<AnyOf<[0, '', false, [], {}]>, false>>,
  Expect<Equal<AnyOf<[]>, false>>,
]

我的答案

type isEmptyObject<T> = T extends object
  ? keyof T extends never
    ? true
    : false
  : false;

type isTrue<T> = T extends []
  ? false
  : T extends []
  ? false
  : T extends 0
  ? false
  : T extends ""
  ? false
  : T extends false
  ? false
  : isEmptyObject<T> extends true
  ? false
  : true;

type AnyOf<T extends readonly any[], R extends boolean = false> = T extends [
  infer P,
  ...infer K
]
  ? isTrue<P> extends true
    ? true
    : AnyOf<K, R>
  : R;

知识点

  1. 对于 false 场景的列举
  2. 对于空对象的判断
  3. 递归

2. Medium isNever

题目要求

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

type cases = [
  Expect<Equal<IsNever<never>, true>>,
  Expect<Equal<IsNever<never | string>, false>>,
  Expect<Equal<IsNever<"">, false>>,
  Expect<Equal<IsNever<undefined>, false>>,
  Expect<Equal<IsNever<null>, false>>,
  Expect<Equal<IsNever<[]>, false>>,
  Expect<Equal<IsNever<{}>, false>>,
]

我的解答

type IsNever<T> = (() => T) extends () => never ? true : false;

知识点

  1. never / false / boolean 这些判断需要额外将其包装成函数/数组才能做判断,单独判断 false extends boolean => true 这是判断不出来的

3. Medium isUnion

题目要求

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

type cases = [
  Expect<Equal<IsUnion<string>, false >>,
  Expect<Equal<IsUnion<string|number>, true >>,
  Expect<Equal<IsUnion<'a'|'b'|'c'|'d'>, true >>,
  Expect<Equal<IsUnion<undefined|null|void|''>, true >>,
  Expect<Equal<IsUnion<{a: string}|{a: number}>, true >>,
  Expect<Equal<IsUnion<{a: string|number}>, false >>,
  Expect<Equal<IsUnion<[string|number]>, false >>,
  // Cases where T resolves to a non-union type.
  Expect<Equal<IsUnion<string|never>, false >>,
  Expect<Equal<IsUnion<string|unknown>, false >>,
  Expect<Equal<IsUnion<string|any>, false >>,
  Expect<Equal<IsUnion<string|'a'>, false >>,
]

我的解答

type IsUnion<T> = Permutation<T>["length"] extends 1 ? false : true;

知识点

  1. 全排列数量大于 2 即可,所以参考使用之前的全排列类型即可。