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

如何为带对象与键参数的ParseErrorIntoString函数定义正确TS类型

问题描述

我需要定义一个辅助函数ParseErrorIntoString,用来解析Axios错误,并把生成的错误消息存入指定对象的指定字符串属性。期望的调用方式如下:

axios.get(...).then(...).catch(ParseErrorIntoString(myClass, 'loadError'));

其中myClass是TypeScript类实例(通常用this代替),loadError是该类的字符串类型属性。参考jest.spyOn的设计思路,要求:

  • 传入非字符串属性时TypeScript能报错
  • 能自动推断类型
  • 解决之前遇到的Type 'string' is not assignable to type T[StringPropertyNames<T>]类型不兼容错误

之前尝试过提取NonFunctionPropertyNames、使用Extract工具类型等方法,但要么无法传入this、自动推断失败,要么允许非字符串属性传入,或者赋值时出现类型错误。

解决方案

通过泛型约束和条件类型可以精准限制属性类型,同时确保函数能正确推断类型并完成赋值。以下是完整实现:

import type { AxiosError } from 'axios';

// 工具类型:提取对象中值为字符串类型的属性名
type StringPropertyNames<T> = {
  [K in keyof T]: T[K] extends string ? K : never;
}[keyof T];

/**
 * 生成Axios错误处理函数,将解析后的错误消息存入指定对象的字符串属性
 * @param target 目标对象(通常是类实例this)
 * @param propName 目标对象的字符串类型属性名
 * @returns Axios错误处理函数
 */
function ParseErrorIntoString<T extends object>(
  target: T,
  propName: StringPropertyNames<T>
): (error: unknown) => void {
  return (error: unknown) => {
    // 解析Axios错误生成字符串消息
    let errorMessage = 'Unknown error';
    if (error instanceof AxiosError) {
      errorMessage = error.response?.data?.message || error.message || errorMessage;
    } else if (error instanceof Error) {
      errorMessage = error.message;
    } else if (typeof error === 'string') {
      errorMessage = error;
    }

    // 类型断言确保赋值安全(propName已被约束为字符串属性)
    target[propName] = errorMessage as T[StringPropertyNames<T>];
  };
}

关键说明

  1. StringPropertyNames<T>工具类型:遍历对象所有属性,仅保留值类型为string的属性名,传入非字符串属性时TypeScript会直接报错,符合预期校验逻辑。
  2. 泛型约束T extends object:确保传入的target是对象类型,支持类实例(包括this)的传入。
  3. 返回函数类型:明确返回接收unknown类型错误的处理函数,适配Axios的catch回调要求。
  4. 类型断言:由于StringPropertyNames<T>已确保propName对应属性为字符串类型,此处断言安全,解决了类型不兼容错误。

使用示例

class MyClass {
  loadError = ''; // 字符串类型属性
  someNumber = 0; // 非字符串属性
}

const myClass = new MyClass();

axios.get('/api/data')
  .then(res => console.log(res))
  // 正确:loadError是字符串属性
  .catch(ParseErrorIntoString(myClass, 'loadError'));

// 错误:Type '"someNumber"' is not assignable to type 'StringPropertyNames<MyClass>'
// .catch(ParseErrorIntoString(myClass, 'someNumber'));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:31:06