昨日一群友发出问题如下
type ABC = {
a: number
b: number
c: number
}
// 上述类型应当至少有一个字段必须
我们来分析问题,先看现有条件, 现有索引集
而我们要得到的类型应当是
type Result = {
a: number
b?: number
c?: number
} | {
a?: number
b: number
c?: number
} | {
a?: number
b?: number
c: number
}
这实质上就是一个含有三个元素的新集合, 可以看到这三个元素与索引集 有着明显的映射关系, 分别将其记为
那么我们就可以得到一个索引族, 将索引族中的集合合并, 就是我们需要的答案
于是我们现在需要做的就是写出的通项公式, 显然, 这公式中包含两个变量, 对象类型 和索引类型 , 每一项又由两部分组成: 一个字段必选, 其他所有字段可选, 我们将其表示为 和 , 那么情况就很明了了, 我们很轻易就写出了如下类型
type Item<T, k extends keyof T> = {
[key in Exclude<keyof T, k>]?: T[key]; // K\{k}
} & {
[key in k]: T[key]; // {k}
};
再下一步就是进行映射获取索引族并进行合并了
type IndexedResult<T> = {
[k in keyof T]: Item<T, k>; // 映射
};
type Result<T> = IndexedResult<T>[keyof T] // 因为值的类型本身就是Union, 此处直接就合并了
完整代码如下, 有兴趣的话自行测试下吧
type Item<T, k extends keyof T> = {
[key in Exclude<keyof T, k>]?: T[key]; // K\{k}
} & {
[key in k]: T[key]; // {k}
};
type IndexedResult<T> = {
[k in keyof T]: Item<T, k>; // 映射
};
type Result<T> = IndexedResult<T>[keyof T] // 因为值的类型本身就是Union, 此处直接就合并了