「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」
其实大多数 TypeScript 开发者,对 TypeScript 的利用,还停留在初级水平。
不信?来试试 TypeScript 每周挑战吧!
第 2 期挑战题目全新开启,答案将在 2021-07-08(周五)下午 17:00 公布
背景
TypeScript 中有很多使用的工具类型,其中包括常用的 Pick<T>,它可以用于从一个类型中提取指定的字段,例如:
interface Type1 {
a: string,
b: boolean,
c: number
}
// { a: string, b: boolean }
type Type2 = Pick<Type1, 'a' | 'b'>;
问题
但如果你 Pick 的是一个 Union Type,则可能出现一些问题,例如下面的 PickData:
type Data = {
type: 'a',
value: {
a: string
},
a1: string,
a2: string,
// ...
} | {
type: 'b',
value: {
b: string
},
b1: string,
b2: string,
// ...
} | {
type: 'c',
value: {
c: string
},
c1: string,
c2: string,
// ...
}; // 可能还有更多项
type PickData = Pick<Data, 'type' | 'value'>;
如你所见,Data 是一个 Union Type,根据其 type 字段值的不同,value 字段呈现出不同的格式。PickData 提取了 type 和 value 字段,显然我们希望这 2 个字段仍然保持它们在 Data 中的匹配关系。
即期望 PickData 等同于:
type PickData = {
type: 'a',
value: {
a: string
}
} | {
type: 'b',
value: {
b: string
}
// ...
} | {
type: 'c',
value: {
c: string
}
};
但实际上,经过 TypeScript 的转换处理,PickData 变成了:(不期望)
type PickData = {
type: "a" | "b" | "c";
value: {
a: string;
} | {
b: string;
} | {
c: string;
};
}
即 TypeScript 解析后的 PickData 失去了 Union Type 中的字段匹配关系。
相应的,这段代码会发生报错:(不期望发生)
function test(data: PickData) {
if (data.type === 'a') {
// ERROR:Property 'a' does not exist on type '{ a: string; } | { b: string; } | { c: string; }'.
console.log(data.value.a);
}
}
题目需求
重新定义 问题 中的 PickData,使其在 Pick 了 type 和 value 字段后仍能保持原始 Data 中的互斥匹配关系。
请尝试在代码量和类型冗余最小的情况下实现。
欢迎你将答案和思路评论在下方评论区,正确答案将在 2021-07-08(周五)下午 17:00 公布。
(正文完)
往期挑战回顾
如果你对使用 TypeScript 进行全栈开发感兴趣,欢迎关注目前世界上唯一支持 TypeScript 复杂类型运行时自动检测和二进制序列化的TypeScript 开源 RPC 框架 —— TSRPC。
GitHub:github.com/k8w/tsrpc
中文文档:tsrpc.cn
视频教程:www.bilibili.com/video/BV1hM…