将 union 转换为 map
Transform union into a map
让我们从这个给定的类型开始:
type Union =
{ type: 'A', a: string } |
{ type: 'B', b: number }
我希望我们在这里结束:
type MappedUnion = {
A: { type: 'A', a: string }
B: { type: 'B', b: number }
}
这是一些伪代码:
type MappedUnion<item in Union> = {[ i: item['type'] ]: item}
我想你可以做到以下几点?尚未详尽测试,但似乎有效。
type Union =
{ type: 'A', a: string } |
{ type: 'B', b: number }
type MappedUnion = {[P in Union['type']]: Union & {type: P}};
const v: MappedUnion = {
'A': {type: 'A', a: "hello"},
'B': {type: 'B', b: 3},
}
遗憾的是,不太管用;如果我这样做
type MappedUnionTarget = {
A: { type: 'A', a: string }
B: { type: 'B', b: number }
}
function cvt1(x: MappedUnion): MappedUnionTarget {
return x;
}
然后我得到 Type '({ type: "A"; a: string; } & { type: "A"; }) | ({ type: "B"; b: number; } & { type: "A"; })' is not assignable to type '{ type: "A"; a: string; }'.
我认为打字稿可以得出结论 ({ type: "B"; b: number; } & { type: "A"; })
与 never
相同。
如果您愿意使用 Typescript 2.8(在撰写本文时尚未发布,如果您从 TypeScript 存储库 git pull
可以使用,并且支持条件运算符 ? :
在类型级别)那么你似乎可以做到
type FilterType<T, K> = (T extends { type: K } ? T : never);
type MappedUnion = {[P in Union['type']]: FilterType<Union, P>};
因为 FilterType<T, K>
是我希望 T & {type: K}
表现的样子。
让我们从这个给定的类型开始:
type Union =
{ type: 'A', a: string } |
{ type: 'B', b: number }
我希望我们在这里结束:
type MappedUnion = {
A: { type: 'A', a: string }
B: { type: 'B', b: number }
}
这是一些伪代码:
type MappedUnion<item in Union> = {[ i: item['type'] ]: item}
我想你可以做到以下几点?尚未详尽测试,但似乎有效。
type Union =
{ type: 'A', a: string } |
{ type: 'B', b: number }
type MappedUnion = {[P in Union['type']]: Union & {type: P}};
const v: MappedUnion = {
'A': {type: 'A', a: "hello"},
'B': {type: 'B', b: 3},
}
遗憾的是,不太管用;如果我这样做
type MappedUnionTarget = {
A: { type: 'A', a: string }
B: { type: 'B', b: number }
}
function cvt1(x: MappedUnion): MappedUnionTarget {
return x;
}
然后我得到 Type '({ type: "A"; a: string; } & { type: "A"; }) | ({ type: "B"; b: number; } & { type: "A"; })' is not assignable to type '{ type: "A"; a: string; }'.
我认为打字稿可以得出结论 ({ type: "B"; b: number; } & { type: "A"; })
与 never
相同。
如果您愿意使用 Typescript 2.8(在撰写本文时尚未发布,如果您从 TypeScript 存储库 git pull
可以使用,并且支持条件运算符 ? :
在类型级别)那么你似乎可以做到
type FilterType<T, K> = (T extends { type: K } ? T : never);
type MappedUnion = {[P in Union['type']]: FilterType<Union, P>};
因为 FilterType<T, K>
是我希望 T & {type: K}
表现的样子。