【问题标题】:Creating a discriminated union using the property names of another type使用另一种类型的属性名称创建可区分联合
【发布时间】:2017-05-11 02:55:40
【问题描述】:

我正在尝试创建一个泛型类型,它从一个类型中获取属性名称和属性类型,并使用它们来创建一个可区分的联合类型。例如:

type FooBar = {
    foo: string;
    bar: number;
};

将映射到:

type FooBarPair = {
    key: "foo",
    value: string
} | {
    key: "bar",
    value: number
}

我最初的尝试是:

type Pairs<T> = {
    [TKey in keyof T]: {
        key: TKey;
        value: T[TKey];
    };
};

type Pair<T> = Pairs<T>[keyof T];

但是当我尝试将其应用于上述类型时:

let pair: Pair<FooBar> = {
    key: "foo",
    value: 3
};

我预计会出现编译错误,但没有。当我检查Pair&lt;FooBar&gt; 的类型时,我发现它等同于:

{
    key: "foo" | "bar";
    value: string | number;
}

我认为这可能是打字稿中的一个错误,但我想看看是否有其他方法可以实现这一点。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    是的,有一种方法可以实现这一点。事实证明,Typescript 推断出所需的类型

     `{ key: "foo"; value: string; } | { key: "bar"; value: number; }`
    

    当您删除中间泛型类型 type Pair&lt;T&gt; = Pairs&lt;T&gt;[keyof T]; 并像 Pairs&lt;FooBar&gt;[keyof FooBar] 一样将其内联扩展时:

    type Pairs<T> = {
        [TKey in keyof T]: {
            key: TKey;
            value: T[TKey];
        };
    };
    
    type FooBar = {
        foo: string;
        bar: number;
    };
    
    
    let pair: Pairs<FooBar>[keyof FooBar] = {
        key: "foo",
        value: 3
    };
    

    完整的错误信息是

    Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
      Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
        Types of property 'value' are incompatible.
          Type 'number' is not assignable to type 'string'.
    

    我不确定在这两种情况下要推断的“正确”类型是什么,但是像 Pair&lt;T&gt; = Pairs&lt;T&gt;[keyof T] 这样的速记类型的引入不应影响 IMO 的类型推断。好像是个bug。

    【讨论】:

    • 谢谢,我同意这似乎是一个错误,我会提出一个打字稿问题。
    猜你喜欢
    • 2020-01-25
    • 2021-05-31
    • 1970-01-01
    • 2019-11-26
    • 2019-05-13
    • 1970-01-01
    • 2021-01-12
    • 2021-07-10
    • 2020-05-01
    相关资源
    最近更新 更多