Middle(20/72)
Middle题共72道,是类型体操的大头
题单(中等)
解答
2・获取函数返回类型
不使用 ReturnType 实现 TypeScript 的 ReturnType<T> 泛型。
例如:
正确解答:
注意参数数组~
3・实现 Omit
不使用 Omit 实现 TypeScript 的 Omit<T, K> 泛型。
Omit 会创建一个省略 K 中字段的 T 对象。
例如:
正确解答:
乍一看很绕,其实搞懂 keyof 和 in 就明白了。
8・Readonly 2
实现一个通用 MyReadonly2<T, K>,它带有两种类型的参数 T和 K。
K指定应设置为 Readonly 的 T的属性集。如果未提供 K,则应使所有属性都变为只读,就像普通的 Readonly<T>一样。
例如
正确解答
结合上面的 实现 Omit 和简单题中的 实现 Readonly 可得出该题的答案。
9・深度 Readonly ⭐
实现一个通用的 DeepReadonly<T>,它将对象的每个参数及其子对象递归地设为只读。 您可以假设在此挑战中我们仅处理对象。数组,函数,类等都无需考虑。但是,您仍然可以通过覆盖尽可能多的不同案例来挑战自己。
例如
正确解答
递归解决,注意特判 Funtion 的情况
10・元组转合集
实现泛型 TupleToUnion<T>,它返回元组所有值的合集。
例如
解答: 没想太多的递归实现 👇
翻了翻 issue 发现的另一个实现,确实哦!
12・可串联构造器 ⭐⭐
我的解答
在 JavaScript 中我们经常会使用可串联(Chainable/Pipeline)的函数构造一个对象,但在 TypeScript 中,你能合理的给它赋上类型吗?
在这个挑战中,你可以使用任意你喜欢的方式实现这个类型 - Interface, Type 或 Class 都行。你需要提供两个函数 option(key, value) 和 get()。在 option 中你需要使用提供的 key 和 value 扩展当前的对象类型,通过 get 获取最终结果。
例如
你只需要在类型层面实现这个功能 - 不需要实现任何 TS/JS 的实际逻辑。
你可以假设 key 只接受字符串而 value 接受任何类型,你只需要暴露它传递的类型而不需要进行任何处理。同样的 key 只会被使用一次。
正确解答:注意 Key 必须为之前没取过的,或是 Value 类型与之前不同的(用例 2 和 3)。
15・最后一个元素
实现一个通用 Last<T>,它接受一个数组 T并返回其最后一个元素的类型。
正确解答:基本送分题
16・出堆
实现一个通用 Pop<T>,它接受一个数组 T,并返回一个由数组 T的前 length-1 项以相同的顺序组成的数组。
例如
额外:同样,您也可以实现 Shift,Push和 Unshift吗?
正确解答:看了小册后不难做出
20・Promise.all ⭐⭐⭐
键入函数 PromiseAll,它接受 PromiseLike 对象数组,返回值应为 Promise<T>,其中 T是解析的结果数组。
正确解答:
疑惑吗?疑惑就对了,请看看这个 pr :Variadic tuple types
62・Type Lookup ⭐⭐
有时,您可能希望根据某个属性在联合类型中查找类型。
在此挑战中,我们想通过在联合类型 Cat | Dog中搜索公共 type字段来获取相应的类型。换句话说,在以下示例中,我们期望 LookUp<Dog | Cat, 'dog'>获得 Dog,LookUp<Dog | Cat, 'cat'>获得 Cat。
正确解答:第一反应如下
翻了翻 issue,很巧妙地一个解答如下:
106・Trim Left
实现 TrimLeft<T> ,它接收确定的字符串类型并返回一个新的字符串,其中新返回的字符串删除了原字符串开头的空白字符串。
例如
正确解答:非常经典的模式提取做匹配!
108・Trim ⭐
实现Trim<T>,它是一个字符串类型,并返回一个新字符串,其中两端的空白符都已被删除。
例如
正确解答:结合上一题,易得 TrimRight 的实现方法,二者结合即可实现 Trim
也可以用第二种解法:
110・Capitalize
实现 Capitalize<T> 它将字符串的第一个字母转换为大写,其余字母保持原样。
例如
正确解答:还是通过模式匹配,使用内置类型 Uppercase 进行大写转换
116・Replace ⭐
实现 Replace<S, From, To> 将字符串 S 中的第一个子字符串 From 替换为 To 。
例如
正确解答:注意 From 为空的情况
119・ReplaceAll ⭐⭐
实现 ReplaceAll<S, From, To> 将一个字符串 S 中的所有子字符串 From 替换为 To。
例如
正确解答:在上题基础上,递归!
191・追加参数
实现一个泛型 AppendArgument<Fn, A>,对于给定的函数类型 Fn,以及一个任意类型 A,返回一个新的函数 G。G 拥有 Fn 的所有参数并在末尾追加类型为 A 的参数。
正确解答:显而易见,本题 easy
296・Permutation ⭐⭐⭐⭐
实现联合类型的全排列,将联合类型转换成所有可能的全排列数组的联合类型。
正确解答:题目字越少,难度越大(x)
本题实现全排列,同时要利用联合类型的分散传参这个特性 Distributive Conditional Types
翻 issue 的时候翻到了这个优秀的解答:TS 类型体操笔记 - 296 Permutation
[T] extends [never] 是由于 never 无法被准确判断,任何extends never的条件语句都会返回never,而我们需要返回的是空数组,在小册中的 套路六:特殊特性要记清 有提到这一点。
298・Length of String ⭐
计算字符串的长度,类似于 String#length 。
正确解答:不讲武德版当然就是 type LengthOfString<S extends string> = S['length'] 当然,讲武德版就是这样 ⬇️
459・Flatten ⭐⭐⭐
在这个挑战中,你需要写一个接受数组的类型,并且返回扁平化的数组类型。
例如:
正确解答:经典的数组拍平,需要注意的是...展开需在外层,Item extends any[] ? ...Flatten<Item> : Item 是不行的......
527・Append to object ⭐
实现一个为接口添加一个新字段的类型。该类型接收三个参数,返回带有新字段的接口类型。
例如:
正确解答:先将交叉类型整出来,再把交叉类型遍历一遍。
看到一种很有趣的 解法
最后更新于
这有帮助吗?