【问题标题】:How to have parameterized key for a type in Typescript如何在 Typescript 中为类型设置参数化键
【发布时间】:2018-12-05 20:47:21
【问题描述】:

我正在将我的 react-native 项目从 Flow 迁移到 TypeScript,而我遇到的一个问题是从 Flow 重新创建这种类型:

declare type ApolloData<T, nodeName: string = 'node'> = {
  [nodeName]: ?T,
  viewer?: ?Viewer,
  placeSearch?: ?PlaceConnection,
  contactIqLookup?: ?ContactIq,
};

这让我可以输入来自 GraphQL 的数据,如下所示:

const data: ApolloData<Space> = fetchData();
const space: Space = data.node;
// OR
const data: ApolloData<Space, 'space'> = fetchData();
const space: Space = data.space;

我尝试在 TypeScript 中重新创建它,这是我的第一次尝试:

type ApolloData<T, nodeName extends string = 'node'> = {
  [node: nodeName]: T | null;
  viewer?: Viewer | null;
  placeSearch?: PlaceConnection | null;
  contactIqLookup?: ContactIq | null;
}

但是,这会产生错误:TS1023: An index signature parameter type must be 'string' or 'number'.

在做了一些研究之后,我了解了Record 类型,这似乎很合适,所以我的第二次尝试更成功了一点:

type ApolloData<T, nodeName extends string = 'node'> = 
    Record<nodeName, T | null> &
    {
      viewer?: Viewer | null;
      placeSearch?: PlaceConnection | null;
      contactIqLookup?: ContactIq | null;
    }

但问题在于,其他属性被键入为viewer: Viewer | null | T 而不仅仅是Viewer | null,因为Record 类型适用于该对象的所有属性。

打字稿中是否有任何方法可以接受通用参数化键和值但也有其他字段?

【问题讨论】:

  • 你为什么说viewer: Viewer | null | T?根据我在创建ApolloData 实例时的测试结果,一切正常......

标签: typescript flowtype


【解决方案1】:

这个怎么样?只需将Record 定义与其他静态属性分开,然后将它们组合起来

type ContactIq = { _type: "ContactIq" };
type PlaceConnection = { _type: "PlaceConnection" };
type Viewer = { _type: "Viewer" };

type DataOnly<T, nodeName extends string> = Record<nodeName, T | null>;

interface OtherAttributes {
  viewer?: Viewer | null;
  placeSearch?: PlaceConnection | null;
  contactIqLookup?: ContactIq | null;
}

type ApolloData<T, nodeName extends string = 'node'> = OtherAttributes & DataOnly<T, nodeName>;

const data1: ApolloData<string> = {
  node: "test",
  viewer: { _type: "Viewer" },
  contactIqLookup: { _type: "ContactIq" },
  placeSearch: { _type: "PlaceConnection" }
}

const data2: ApolloData<string, "abc"> = {
  abc: "test",
  viewer: { _type: "Viewer" },
  contactIqLookup: { _type: "ContactIq" },
  placeSearch: { _type: "PlaceConnection" }
}

【讨论】:

    猜你喜欢
    • 2017-07-28
    • 2019-06-13
    • 1970-01-01
    • 2021-04-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2020-04-08
    相关资源
    最近更新 更多