携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
1. 引言
接着上一节中,接下来我们继续Ts中等篇的题型练习
https://github.com/type-challenges/type-challenges/blob/main/README.zh-CN.md 提供的TypeScript 类型体操姿势合集题型,目的是为了让大家更好的了解TS的类型系统,编写自己的类型工具,或者单纯的享受挑战的乐趣!
2. 题型
- BEM style string:块、元素、修饰符方法(BEM)是CSS中常用的类命名约定。
例如,块组件将表示为btn,依赖于块的元素将表示为btn__price,改变块样式的修饰符将表示为btn- big或btn__price- warning。
实施BEM<B、E、M>从这三个参数生成字符串union。其中B是字符串字面值,E和M是字符串数组(可以为空)。
思路: 首先确认该方法需要使用到模板字面量类型,在配合元组的[number] 可映射出元组内部元素,执行分布式条件语句操作,返回个类型值拼接组合后的联合类型;完成。 解答:
type BEM<B extends string, E extends string[], M extends string[]> = `${B}${E extends [] ? '' : `__${E[number]}`}${M extends [] ? '' : `--${M[number]}`}`
type Demo = BEM<'btn', ['price'], []> // type Demo = "btn__price"
type Demo1 = BEM<'btn', ['price'], ['warning', 'success']> // type Demo1 = "btn__price--warning" | "btn__price--success"
type Demo2 = BEM<'btn', [], ['small', 'medium', 'large']> // type Demo2 = "btn--small" | "btn--medium" | "btn--large"
- InorderTraversal:实现二叉树的顺序遍历的类型版本。
const tree1 = {
val: 1,
left: null,
right: {
val: 2,
left: {
val: 3,
left: null,
right: null,
},
right: null,
},
} as const
type A = InorderTraversal<typeof tree1> // [1, 3, 2]
思路: 首先处理此题需要遍历树,在Ts中遍历树需要使用递归操作,也就是说需要吧目标对象T 通过和自定义对象类型 TreeNode 的extends 来判断是否符合目标类型;当符合时候,使用递归对应left树和right树,合并上目标val值; 解答:
interface TreeNode {
val: number
left: TreeNode | null
right: TreeNode | null
}
type InorderTraversal<T extends TreeNode | null> = [T] extends [TreeNode] ?
[...InorderTraversal<T['left']>, T['val'], ...InorderTraversal<T['right']>] : []
const tree1 = {
val: 1,
left: null,
right: {
val: 2,
left: {
val: 3,
left: null,
right: null,
},
right: null,
},
} as const
const tree2 = {
val: 1,
left: null,
right: null,
} as const
const tree3 = {
val: 1,
left: {
val: 2,
left: null,
right: null,
},
right: null,
} as const
const tree4 = {
val: 1,
left: null,
right: {
val: 2,
left: null,
right: null,
},
} as const
type Demo = InorderTraversal<null> // type Demo = []
type Demo2 = InorderTraversal<typeof tree1> // type Demo2 = [1, 3, 2]
type Demo3 = InorderTraversal<typeof tree2> // type Demo3 = [1]
type Demo4 = InorderTraversal<typeof tree3> // type Demo4 = [2, 1]
type Demo5 = InorderTraversal<typeof tree4> // type Demo5 = [1, 2]
- Flip: 实现just-flip-object类型。例子:
Flip<{ a: "x", b: "y", c: "z" }>; // {x: 'a', y: 'b', z: 'c'}
Flip<{ a: 1, b: 2, c: 3 }>; // {1: 'a', 2: 'b', 3: 'c'}
Flip<{ a: false, b: true }>; // {false: 'a', true: 'b'}
思路: 此题需要key和value 互换,通过keyof映射类型描述对象时,as 追加变形通过模板字面量类型设置值为键,并键 为值从而值和键互换; 注意:但是这样有几个测试会挂掉,由于 key 的位置只能是 string 或者 number 或者 boolean 所以挂了
因此我们可以限定一下 value 的类型 Record<string, string | number | boolean>
这样还是有挂掉的,是 Flip<{ pi: 3.14; bool: true }>,很显然 boolean 不能作为 key,需要转化成字符串,我们用模版强行转一下即可 解答:
type Flip<T extends Record<string, string | number | boolean>> = {
[P in keyof T as `${T[P]}`]: P
}
type Demo = Flip<{ pi: 'a' }> // type Demo = {a: "pi";}
type Demo2 = Flip<{ 3.14: 'pi'; true: 'bool' }> // type Demo2 = {pi: 3.14;bool: "true";}
type Demo3 = Flip<{ val2: 'prop2'; val: 'prop' }> // type Demo3 = {prop2: "val2";prop: "val";}