简体   繁体   English

如何为 Typescript 中的未知 object 属性动态分配名称和类型

[英]How to dynamically assign a name and type to unknown object property in Typescript

I'm using Shopify's rest client for node and its request and response look something like this:我正在使用 Shopify 的 rest 客户端作为节点,它的请求和响应如下所示:

  • request要求
client.get({
  path: 'orders/count.json',
  query: { fulfillment_status: 'unfulfilled' }
})
  • If there's an error:如果有错误:
{
  "errors": "[API] Invalid API key or access...",
  "code": 2342,
  "statusText": "Authentication Error",
  "Headers": "..."
}
  • If there's no error:如果没有错误:
{
  "body": { "count": 8 },
  "code": 2342,
  "statusText": "Authentication Error",
  "Headers": "..."
}

I'd like to add some boilerplate over this client library so that I can get the typings of the response.我想在这个客户端库上添加一些样板,以便我可以获得响应的类型。 This is what I'm trying to do but it's not working too well:这是我正在尝试做的,但效果不太好:

const customClient = {

  get: async <T, K extends string>(params: GetRequestParams) => {
      const response = (await client.get(params));
      if (response.body.errors) return { errors: response.body.errors };
      // somehow index it. obviously not with the type declaration???
      return { [K]: response.body[K] as T };
    },

}

With the hopes that I can use it as.希望我可以将其用作。

const { count, error } = customClient.get<number, "count">({ ... });

Any help would be appreciated.任何帮助,将不胜感激。 I have an entire file of the Shopify API types that I would like to leverage.我有一个我想利用的 Shopify API 类型的完整文件。 A solution to this would be perfect解决这个问题将是完美的

A possible implementation can look like this:一个可能的实现如下所示:

const customClient = {
  get: async <T, K extends string>(params: GetRequestParams): 
      Promise<Partial<Record<K, T> & { errors: string }>> => 
    {
      const response = (await client.get(params));
      if (response.body.errors) return { errors: response.body.errors } as any;

      return { 
        [Object.keys(response)[0]]: response[Object.keys(response)[0]] 
      } as any
    },
}

As you correctly noted, we can't use the TypeScript generic types when constructing the returning object.正如您正确指出的那样,在构造返回的 object 时,我们不能使用 TypeScript 泛型类型。 We need to use JavaScript features instead.我们需要改用 JavaScript 功能。 In this case I just took the first key of the response and used it for the key of the returning object as well as to index the response object.在这种情况下,我只取response的第一个键并将其用作返回的 object 的键以及索引response object。

The return type of the function is a Promise consisting of both a Record with K and T as keys and values and the error type. function 的返回类型是一个Promise ,它由以KT作为键和值的Record和错误类型组成。 I used Partial here since they are not both required.我在这里使用了Partial ,因为它们都不是必需的。

Destructing the response leads to the correct types now:现在破坏响应会导致正确的类型:

async function main(){
  const { count, errors } = await customClient.get<number, "count">({} as any);
  // count: number | undefined
  // errors: string | undefined
}

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Typescript Object 的类型未知 - Typescript Object is of type unknown 如何动态访问 TypeScript 中的 object 属性 - How to dynamically access object property in TypeScript 无法动态分配 JS object 属性 - Can't dynamically assign JS object property 打字稿错误:量角器中的“未知”类型不存在“清除”或“发送”属性 - Typescript error: Property 'clear' or 'send' does not exist on type 'unknown' in protractor 类型“数组”的属性在领域对象服务器中具有未知的对象类型 - Property of type 'array' has unknown object type in realm object server 错误 TS2571:对象在打字稿中属于“未知”类型 - error TS2571: Object is of type 'unknown' in typescript 如何在 typescript 中动态设置 object 密钥 - How to dynamically set an object key in typescript 当我需要更改对象中的属性类型时,如何正确使用 TypeScript - How do I work with TypeScript correctly when I need to change a type of a property in an object API 在 Typescript 中接收到未知的正文或参数,如何检查类型 - API receiving unknown body or parameter in Typescript, how to check the type Map 和 FlatMap 抛出错误“属性 &#39;map&#39; 在 Typescript 中的类型 &#39;unknown&#39; 上不存在 - Map and FlatMap throwing error "Property 'map' does not exist on type 'unknown' in Typescript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM