typescript 无法推断键的值类型

问题描述 投票:0回答:1

我定义这个类型的方式有什么问题

type Payload<Es> = {
  trigger:
    Es extends Record<infer K, infer V>
     ? { key: K, data: V } : never
}

type Evs = {
  "item.1": { ok: "Y", code: number }
  "item.2": 1 | 0
}
const payload: Payload<Evs> = {
  trigger: {
    key: "item.1",
    data: 1
  }
}

payload.trigger.data
没有像我预期的那样推断出来

预计

{ ok: "Y", code: number }

我得到了什么

0 | { ok: "Y", code: number } | 1

typescript typescript-generics inferred-type
1个回答
0
投票

Record<K, V>
实用程序类型是与具有类型
K
属性键和
V
类型属性值的对象相对应的类型。但特定的键不与特定的值关联。如果您从
{a: string, b: number}
开始,并尝试从中推断
Record<K, V>
,您将得到
Record<"a" | "b", string | number>
。这与您从
{a: number, b: string}
获得的类型相同。所以你真的不想在这里推断出
Record
,除非你想要将所有属性混合在一起。

相反,您实际上只需要映射类型,迭代每个键

K
,并生成相应的对象类型,然后索引到映射的类型以获得属性的联合。也就是说,您需要一个分布式对象类型(如microsoft/TypeScript#47109中所创造):

type Payload<E> = {
  trigger: { [K in keyof E]: { key: K, data: E[K] } }[keyof E]
}

您可以验证这是否为您提供了您正在寻找的内容:

type Evs = {
  "item.1": { ok: "Y", code: number }
  "item.2": 1 | 0
}

type PEvs = Payload<Evs>;
/* type PEvs = {
    trigger: {
        key: "item.1";
        data: {
            ok: "Y";
            code: number;
        };
    } | {
        key: "item.2";
        data: 0 | 1;
    };
} */

const payload: Payload<Evs> = {
  trigger: {
    key: "item.1",
    data: 1 // error!
  }
}

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.