我正在向一个API端点发送请求,它的响应根据响应中名为productType的字段而有所不同.例如,API可以返回如下响应:

// response 1
{
    productType: 'Product1',
    product: 'Some product information'
}

// response 2
{
    productType: 'Product2',
    product: {moreNestedFields: 'Some product information'}
}

我希望能够根据productType在我的客户端代码中运行不同的逻辑(缩小类型).

以下是我这样做的简化try :

type Product = 'Product1' | 'Product2';
type MyResponse<TProduct extends Product> = {
  product: TProduct extends 'Product1' ? 'SomeType' : 'SomeOtherType';
  productType: TProduct;
};

function getResponse<T extends Product>() {
  // This is accually some fetch request
  return {} as MyResponse<T>;
}


const response = getResponse();

if (response.productType === 'Product1') {
   //  myProduct is not type narrowed?
   // I am expecting it to only have 'SomeType' but its type is <'SomeType' | 'SomeOtherType'>
  const myProduct = response.product;                      
  // do something with myProduct
} else {
  // ..
}

我遗漏了什么?我怎样才能做到这一点呢?

推荐答案

您应该使用discriminated union types而不是泛型. 更新的MyResponse类型:

type Product = 'Product1' | 'Product2';
type MyResponse =
  | {
      productType: Extract<Product, 'Product1'>;
      product: 'SomeType';
    }
  | {
      productType: Extract<Product, 'Product2'>;
      product: 'SomeOtherType';
    };

注:添加Extract是为了更好地确保类型安全,以避免输入错误.

playground

如果所有类型的答复都有公共字段,则可以将它们放在单独的类型中,并将它们与联合相交:

type CommonFields = {
  status: string;
};

type MyResponse = CommonFields &
  (
    | {
        productType: Extract<Product, 'Product1'>;
        product: 'SomeType';
      }
    | {
        productType: Extract<Product, 'Product2'>;
        product: 'SomeOtherType';
      }
  );

playground

Typescript相关问答推荐

为什么当类类型与方法参数类型不兼容时,该函数可以接受类类型

输入具有相同键但值类型不同的对象

如何在类型脚本中使用条件陈述循环

数组文字中对象的从键开始枚举

带占位符的模板文字类型何时扩展另一个?

学习Angular :无法读取未定义的属性(正在读取推送)

表单嵌套太深

如何在Reaction Query Builder中添加其他字段?

Angular 17子路由

Fp-ts使用任务的最佳方法包装选项

如何在ANGLE中注册自定义验证器

如何从输入中删除值0

有没有办法防止类型交集绕过联合类型限制?

是否可以强制静态方法将同一类型的对象返回其自己的类?

接受字符串或数字的排序函数

打印脚本中正则函数和函数表达式的不同类型缩小行为

Typescript .根据枚举输入参数返回不同的对象类型

VUE 3类型';字符串';不可分配给类型';参考<;字符串&>

如何键入';v型';

可以';t使用t正确地索引对象;联合;索引类型