1

所以我在 typescript 中发现了一个技巧,通过将类型映射到键值对然后使用该keyof类型创建一个可以是映射中任何值的类型,将对象类型转换为可区分的联合。这是一个简单的例子:

type SourceType =
{
    foo: number,
    bar: string
};
type MapWithKey<T> = {[P in keyof T]: { key: P, value: T[P] }}
type DescriminatedUnion = MapWithKey<SourceType>[keyof SourceType];
//The DescriminatedUnion now has the following type
DescriminatedUnion ≡ {key:"foo",value:string} | {key:"bar",value:number}

如果您想指定一个非常大的可区分联合,这非常有用,但是当您尝试使此构造完全通用时,您最终会得到不同的类型。

type MakeDescriminatedUnion<T> = MapWithKey<T>[keyof T];
type DescriminatedUnion = MakeDescriminatedUnion<SourceType>
//The DescriminatedUnion now has the followin type
DescriminatedUnion ≡ {key:"foo"|"bar",value:number|string}

这应该是相同的类型,但由于某种原因它不是。我试图查看打字稿文档以找到这种行为的一些原因,但我不能。有谁知道这种差异背后的原因?或者更好的是,有没有人知道一种解决这种行为并使其完全通用的方法?

4

1 回答 1

1

是的,这个问题困扰着我其他很多人。令人惊讶的是,正如 @artem 所提到的,针对 TypeScript 2.6的修复程序就在今天推出!

同时,对于我们这些停留在 TypeScript 2.4 领域的人来说,有一个使用默认泛型类型参数的解决方法:

type MakeDiscriminatedUnion<T, M extends MapWithKey<T> = MapWithKey<T>> = M[keyof T];
type DiscriminatedUnion = MakeDiscriminatedUnion<SourceType> // okay now

的实际值在M您使用 之前不会被评估MakeDiscriminatedUnion<SourceType>,因此编译器没有机会M[keyof T]像上面那样“简化”它。

无论如何,您可以选择是使用解决方法还是等待 TypeScript 2.6。希望有帮助。祝你好运!

于 2017-08-25T23:38:07.870 回答