如何编写一个单独将数组与不同类型的对象分组的函数?

时间:2017-11-26 16:15:11

标签: javascript arrays typescript

此问题涉及最新版本的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必须获取包含键列表的某种对象,因此它不能都是可擦除的类型信息。

我有自己的尝试解决方案,我将作为答案添加,但我也在寻找其他可能更好的解决方案。

1 个答案:

答案 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>

但是,有一些问题:

  1. 奇怪的x.D值。实际上,只要将它转换为类型null,就可以用任何其他值替换它们。他们完全被忽视了。在API中看到这一点非常奇怪。
  2. 您还可以将A/B/C放入密钥对象中,它将起作用。
  3. 您也可以将D : null as C放入选择器功能中,即使x => "hello"的类型为type,它也会有效。