【Typescript 系列】类型体操之中等篇题型(第七节)解读

95 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情

1. 引言

接着上一节中,接下来我们继续Ts中等篇的题型练习 https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!

2. 题型

  1. Flatten:在这个挑战中,你需要写一个接受数组的类型,并且返回扁平化的数组类型。
type flatten = Flatten<[1, 2, [3, 4], [[[5]]]]> // [1, 2, 3, 4, 5]

思路:    首先先现在入参类型,之后使用【】解构+infer关键字抽离数组第一项以及第一项以外内容,判断第一项是否为多维数组:1.如果是使用递归方法再次引用数组第一项以及第一项以外数据,一层层递归,直到结束位置,最后返回值回抛组成扁平化数组;2.否则 判断第一项以外的数组是否为多维数组,是的话也采取递归,直到最底层会抛数据完成数组扁平化,3.或者是数组成员是其他类型数据直接回抛。 解答:

type Flatten<List extends unknown[]> = List extends [infer E, ...infer R]
  ? E extends unknown[]
    ? [...Flatten<E>, ...Flatten<R>]
    : [E, ...Flatten<R>]
  : List

type Demo = Flatten<[]> // type Demo =  []
type Demo2 = Flatten<[1, 2, 3, 4]> // type Demo = [1, 2, 3, 4]
type Demo3 = Flatten<[1, [2]]> // type Demo = [1, 2]
type Demo4 = Flatten<[1, 2, [3, 4], [[[5]]]]> // type Demo = [1, 2, 3, 4, 5]
type Demo5 = Flatten<[{ foo: 'bar'; 2: 10 }, 'foobar']> // type Demo = [{ foo: 'bar'; 2: 10 }, 'foobar']

  1. Append to object:实现一个为接口添加一个新字段的类型。该类型接收三个参数,返回带有新字段的接口类型。
type Test = { id: '1' }
type Result = AppendToObject<Test, 'value', 4> // expected to be { id: '1', value: 4 } 

思路:    使用映射类型的方式配合keyof拿到循环T变量里面的键值,在使用类型合并设定对应的键值。 解答:

type AppendToObject<T, U extends string, V> = { [K in (keyof T) | U]: K extends keyof T ? T[K] : V }
type Demo = AppendToObject<test1, 'home', boolean> // type Demo = {home: boolean;key: "cat";value: "green";}
type Demo2 = AppendToObject<test2, 'home', 1> // type Demo2 = {home: 1;key: "dog" | undefined;value: "white";sun: true;}
type Demo3 = AppendToObject<test3, 'isMotherRussia', false | undefined> // type Demo3 = {key: "cow";value: "yellow";sun: false;isMotherRussia: false | undefined;}
type test1 = {
  key: 'cat'
  value: 'green'
}


type test2 = {
  key: 'dog' | undefined
  value: 'white'
  sun: true
}

type test3 = {
  key: 'cow'
  value: 'yellow'
  sun: false
}
  1. Absolute:实现一个接收string,number或bigInt类型参数的Absolute类型,返回一个正数字符串。
type Test = -100;
type Result = Absolute<Test>; // expected to be "100"

思路:    使用模板字面量配合infer 关键字去除负数,返回正整数字符串

解答:

type Absolute<T extends number | string | bigint> = `${T}` extends `-${infer N}` ? N : `${T}`;
type Demo = Absolute<0> // type Demo =  "0"
type Demo2 = Absolute<-0> // type Demo =  "0"
type Demo3 = Absolute<10> // type Demo =  "10"
type Demo4 = Absolute<-5> // type Demo =  "5"
type Demo5 = Absolute<'0'> // type Demo =  "0"
type Demo6 = Absolute<'-0'> // type Demo =  "0"
type Demo7 = Absolute<'-5'> // type Demo =  "5"
type Demo8 = Absolute<-1_000_000n> // type Demo =  "1000000"
type Demo9 = Absolute<9_999n> // type Demo =  "9999"