首页 > 解决方案 > 将类型映射到字符串属性

问题描述

我有一堆数据类型,它们都包含一个属性dataType,我将每个类型映射到该值:

interface GroupData {
    dataType: "group";
    name: string;
    people: PersonData[];
}

interface PersonData {
    dataType: "person";
    name: string;
    email: string;
    messages: MessageData[];
}

interface MessageData {
    dataType: "message";
    message: string;
    timestamp: number;
}

interface DataTypeMap {
    group: GroupData;
    person: PersonData;
    message: MessageData;
}

这符合我的目的,但有点手动。在我的实际应用程序中,我有更多的数据类型,并且它们经常变化。我想要的是能够使这个过程自动化一点。到目前为止,这与我来的一样接近:

type DataType = GroupData
    | PersonData
    | MessageData;

type DataTypeMap = {
    [(T in DataType)["dataType"]]: T;
};

调节单个数据类型的联合比键必须具有特定值的映射要容易得多;但是,这在 TypeScript 中并不符合犹太教规。我收到以下 TS 错误:

A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
Cannot find name 'T'.
'DataType' only refers to a type, but is being used as a value here.

据我所知,这些都是我的语法问题。我 90% 确定您不能使用in非字符串的联合,并且在索引签名中使用括号选择器感觉像是一种延伸。

是否可以根据所有数据类型都具有的属性映射数据类型列表?

标签: typescript

解决方案


你是如此接近!这就是我们想要的:

type DataTypeMap = {
    [T in DataType['dataType']]: Extract<DataType, {dataType: T}>;
};

DataType是所有类型接口的并集。 DataType['dataType']是所有类型名称字符串文字的并集。

在我们的地图中,我们说键是那些string名称。对于每个键,我们都想找到对应的interface. 我们使用Extract只获取可以拥有的工会成员{dataType: T}

这解决了:

type DataTypeMap = {
    group: GroupData;
    person: PersonData;
    message: MessageData;
}

打字稿游乐场链接


推荐阅读