[typof T] 在具有与硬编码类型不同的语义的泛型中的原因?

Reason for [typof T] in generics having different semantics that a hard coded type?

所以我在打字稿中发现了一个技巧,通过将类型映射到键值对,然后使用 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}

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

是的,this issue has bitten me and quite a few others. It's amazing that, as @artem mentions, a fix 为 TypeScript 2.6 定于今天推出!

与此同时,对于我们这些停留在 TypeScript 2.4 领域的人来说,有一个使用 default generic type parameters 的解决方法:

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

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

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