如果我有一个对象的 Typescript 类型,我如何使用其值的类型?

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

我有一个提取嵌套 GraphQL 数据的函数:

const data = {
   cats: { edges: [ {node: cat1}, {node: cat2} ] },
   dogs: { edges: [ {node: dog1}, {node: dog2}, {node: dog3} ] },
}

const extracted = extract<{ cats: CatType, dogs: DogType }>(data);

// extracted = {
//   cats: [cat1, cat2], // CatType[]
//   dogs: [dog1, dog2, dog3], // DogType[]
// }

但是,我很难获得正确的类型签名。我想说的是“这个函数接受带有字符串键和类型值的接口的参数,并返回一个具有相同键的对象以及相应类型的数组值”。

换句话说,如果函数得到

{ cats: nestedCats }
,它应该返回
{ cats: CatType[] }
(即
cats: T['cat'])
)。如果它得到
{ dogs: nestedDogs }
,它应该返回
{ dogs: DogType[] }
,鱼
{ fishes: FishType[] }
,等等。如果它获取多种类型,它应该返回一个包含所有类型数组的对象。

现在我有一个签名:

export const extractNodesFromData = <T extends { [key: string]: any }> =>

但是,我有两个问题:

  • A)在我的函数内,当我迭代数据时,如何引用该数据的类型?例如:

    Object.entries(data).map(([key, value]) => // How do I type value?

    Object.entries(data).map((([key, value: T[key]]) => // Doesn't work

  • B)我无法指定函数的返回类型:我不知道如何将我提供的类型(

    { cat: CatType, ...}
    )转换为相同的类型,但对于数组(即
    { cat: CatType[], ...}
    )...这就是该函数实际返回的内容。

完整可重现示例

这对实际问题没有任何帮助,但有些人可能会发现查看其他(不相关的)JS/TS 有帮助:

interface CatType {
   id: string;
   name: string;
   catBreed: string;
}
interface DogType {
   id: string;
   name: string
   dogBreed: string;
}

const extractNodes = <T>(data): T[] =>
    data?.edges?.map(({ node }) => node);

const extractNodesFromData = <T extends { [key: string]: any }> (data: any) => 
Object.entries(data).reduce(
    (extracted, [key, value: T[key]]) => ({
      ...extracted,
      [key]: extractNodes<T[key]>(value)
    }),
    {}
  )
typescript
1个回答
0
投票

这个答案的所有功劳都归功于@jcalz,他没有提交答案,但很友善地提供了一个完全工作的沙箱,它不仅回答了我的问题:它还为我修复了我的代码!我只是想学习如何钓鱼,而不是要求在它上面得到鱼......但我会接受:)

JCalz,请提交答案:我很乐意删除此答案并接受它(即使它是此答案的副本)。

如果您想访问泛型类型的属性,只需:

  1. 让你的泛型类型简单地扩展

    object

    • 不要延长
      { [key: string]: any }
      ,这是我尝试过的
  2. 在参数内部,使用语法

    K in keyof T
    作为解构后的参数的键。换句话说,不要执行以下任一操作:

    (data: any) =>

    (data: { [key : string[: any }) =>

    改为:

    (data: { [K in keyof T]: // ...无论你的值是什么

    在我的具体情况下(提取

    edge
    node
    ),那就是:

    (data: { [K in keyof T]: { edges: { node: T[K] }[] } })

  3. 上面的代码演示了我的问题的答案:要访问类型的属性,您do使用

    T[K]
    语法,这就是我正在尝试的,但因为它是与
    [K in keyof T]
    相同的表达式的一部分您可以访问有效的
    K

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