此问题涉及最新版本的TypeScript,因此可能会在更新版本发布时更新。
假设我有以下几种类型:
type A = {type: "A"; a_data : string};
type B = {type : "B"; b_data : string};
type C = {type : "C'; c_data : string};
我定义了以下的析取类型:
type AnyABC = A | B | C;
我的目标是拥有一个近似形式的函数:(您可以删除/添加一些参数。)
function groupByKey(array : AnyABC[], key : (abc : AnyABC) => string)
这将接受一组混合的A, B, C
个对象并返回一个对象或ES6 Map
,其中包含A[]
,B[]
和{{1}的单独区域}}。所以你可以去:
C[]
let a = result.A[0]
将被强类型为a
。
执行此操作的实际代码只是简单的Javascript而不太重要。更重要的是如何正确编码类型。
即使A
中没有A
- 类型的值,我仍然希望AnyABC[]
bin为空数组A
。这意味着Javascript必须获取包含键列表的某种对象,因此它不能都是可擦除的类型信息。
我有自己的尝试解决方案,我将作为答案添加,但我也在寻找其他可能更好的解决方案。
答案 0 :(得分:0)
首先,我们定义:
[]
这是一种类型,它将对键名进行编码以及生成的元素类型应该是什么。
然后我们定义:
type KeySetFor<T> = {
[key : string] : T;
}
这是结果类型以及我们的函数返回的内容。
现在出现了棘手的部分,功能定义:
type KeyResultSetFor<T> = {
[key in keyof T] : T[key][]
}
你可以这样调用这个函数:
function groupByKeys<T, TKeySet extends KeySetFor<T>>(array : T[], possibleKeys : TKeySet, selector : (k : T) => string) : KeyResultSetFor<TKeySet>
这很有效,我的IDE的AutoComplete功能正确显示let arr = [] as AnyABC[];
let x = Arr.groupByKeys(arr, {
A : null as A,
B : null as B,
C : null as C
}, x => x.type);
有成员x
,如果我尝试访问{A : A[], B : B[], C : C[]}
,编译的TypeScript会正确抱怨。< / p>
但是,有一些问题:
x.D
值。实际上,只要将它转换为类型null
,就可以用任何其他值替换它们。他们完全被忽视了。在API中看到这一点非常奇怪。A/B/C
放入密钥对象中,它将起作用。D : null as C
放入选择器功能中,即使x => "hello"
的类型为type
,它也会有效。