You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中为Shopify REST客户端响应动态分配类型

Shopify Node.js REST客户端的TypeScript类型封装方案

问题背景

我正在使用Shopify的Node.js REST客户端,相关请求与响应示例如下:

  • 请求示例:
client.get({
  path: 'orders/count.json',
  query: { fulfillment_status: 'unfulfilled' }
})
  • 错误响应示例:
{
  "errors": "[API] Invalid API key or access...",
  "code": 2342,
  "statusText": "Authentication Error",
  "Headers": "..."
}
  • 成功响应示例:
{
  "body": { "count": 8 },
  "code": 200,
  "statusText": "OK",
  "Headers": "..."
}

我希望封装该客户端,让调用时能自动获取响应的TypeScript类型,同时期望调用方式如下:

const { count, errors } = await customClient.get({ path: 'orders/count.json', query: { fulfillment_status: 'unfulfilled' } });

我已有完整的Shopify API类型文件,之前的尝试效果不佳:

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 };
      // 此处无法正确关联类型与响应字段
      return { [K]: response.body[K] as T };
    },
}

解决方案

1. 基于Shopify API类型定义路径-响应映射

利用已有的Shopify API类型,定义路径到对应响应体类型的映射,让TypeScript能根据请求路径自动推导响应类型:

// 假设已有的Shopify API类型中包含这些响应类型
import type { OrderCountResponse, OrderResponse } from './shopify-api-types';

// 定义路径与响应体的映射
type ShopifyApiPathMap = {
  'orders/count.json': OrderCountResponse; // 结构为 { count: number }
  'orders.json': OrderResponse[];
  // 其他API路径可继续扩展
};

// 提取所有合法的API路径类型
type ShopifyApiPath = keyof ShopifyApiPathMap;

// 定义Get请求参数类型
type GetRequestParams<TPath extends ShopifyApiPath> = {
  path: TPath;
  query?: Record<string, string | number | boolean>;
};

2. 封装带类型推导的get方法

通过条件类型区分成功/错误响应,同时根据路径自动推导返回的数据字段:

const customClient = {
  get: async <TPath extends ShopifyApiPath>(params: GetRequestParams<TPath>) => {
    const response = await client.get(params);

    // 错误响应处理:返回包含errors的对象
    if ('errors' in response.body) {
      return {
        errors: response.body.errors,
        code: response.code,
        statusText: response.statusText
      } as const;
    }

    // 成功响应:根据路径映射提取对应数据,同时返回响应元信息
    const responseBody = response.body as ShopifyApiPathMap[TPath];
    // 提取响应体的唯一键(比如count、orders等)
    type ResponseKey = keyof typeof responseBody;
    const dataKey = Object.keys(responseBody)[0] as ResponseKey;

    return {
      [dataKey]: responseBody[dataKey],
      code: response.code,
      statusText: response.statusText,
      headers: response.Headers
    } as const;
  }
};

3. 类型安全的调用示例

现在调用时无需手动传入泛型,TypeScript会自动根据路径推导返回类型:

// 调用订单统计接口,自动推导count为number类型
const result = await customClient.get({
  path: 'orders/count.json',
  query: { fulfillment_status: 'unfulfilled' }
});

if ('errors' in result) {
  // 错误分支:result.errors、result.code等类型都能正确推导
  console.error('请求失败:', result.errors);
} else {
  // 成功分支:result.count自动推导为number
  console.log('未完成订单数:', result.count);
}

优化说明

  • 无需手动传入泛型参数,TypeScript会根据请求的path自动匹配对应的响应类型,避免手动传参出错。
  • 通过'errors' in result的类型守卫,TypeScript能自动区分成功/错误分支的类型,实现类型安全的分支处理。
  • 如果Shopify API类型中已经包含完整的路径与响应映射,可以直接复用,无需手动定义ShopifyApiPathMap,只需提取路径类型即可。

内容的提问来源于stack exchange,提问作者Dimitri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 03:03:21