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

React+TypeScript+Axios中TypeError: is not a function问题求助

问题:Axios返回数据无法实例化为Class对象,调用方法时报错

通过Axios从后端获取的数据未被正确实例化为Class类对象,调用类方法时出现Uncaught TypeError TypeError: object.method is not a function错误。

示例代码

父组件(获取数据并传递给子组件)

// imports
const Component: React.FC<ComponentProps> = () => {
  const { id } = useParams<{ id: string }>();
  const [object, setObject] = useState<Class>(new Class());
  
    useEffect(() => {
        (async () => {
            try {
                const object = await Service.getById(id);
                setObject(object);
            } catch (err) {
                //error handling
            } finally {
                cleanup();
            }
        })();

        return () => {
            // cleanup
        };
    });

  return  (
    <Container title={object.name}>
          <Child object={object} />
    </Container>
  );
};

export default Component;

子组件(调用类方法触发错误)

// imports
interface Interface {
  object: Class;
}

const Child: React.FC<Interface> = ({ object }) => {

  object.callSomeFunction(); // 此处触发错误

  return (
    <SomeJSXCode />
  );
};

export default Child;

Class类定义(临时用静态from方法,但不适用于多属性类)

export class Class {
  id: string = '';
  name: string = '';
  callSomeFunction = () => {
    // do something;
  }
  static from(object: Class): Class {
    const newInstance = new Class();
    newInstance.id = object.id;
    newInstance.name = object.name;
    // 要是类有很多属性,这种写法太繁琐
    return newInstance;
  }
}

Service服务代码

// imports

const URL = 'http://localhost:8000';

const baseConfig: AxiosRequestConfig = {
  baseURL: URL,
  headers: { 'Content-Type': 'application/json' },
  withCredentials: true,
};

export const backend = axios.create({
  ...baseConfig,
  baseURL: URL + '/someEndpoint',
});

export const Service = {
  async getById(id: string): Promise<Class> {
      try {
        const { data } = await backend.get<Class>(`/${id}`);
        return data;
      } catch (err) {
        throw new Error(err.response.data.message);
    }
  },
};

解决方案

核心原因

Axios返回的data只是一个普通JavaScript对象,虽然TypeScript通过类型断言标记为Class,但它并没有被实例化,自然没有Class实例的方法属性(包括类里定义的箭头函数属性,这类属性只有通过new Class()创建的实例才会拥有)。

优化方案(替代手动赋值的from方法)

方案1:改造构造函数实现批量赋值

修改Class的构造函数,让它可以接收普通对象并批量赋值:

export class Class {
  id: string = '';
  name: string = '';

  constructor(obj?: Partial<Class>) {
    if (obj) {
      Object.assign(this, obj);
    }
  }

  callSomeFunction = () => {
    // do something;
  }
}

然后在Service中返回数据时实例化Class:

async getById(id: string): Promise<Class> {
    try {
      const { data } = await backend.get(`/${id}`);
      return new Class(data); // 用返回的数据实例化Class
    } catch (err) {
      throw new Error(err.response.data.message);
  }
}

方案2:优化静态from方法支持批量赋值

如果不想修改构造函数,直接升级静态from方法:

export class Class {
  id: string = '';
  name: string = '';
  callSomeFunction = () => {
    // do something;
  }

  static from(obj: Partial<Class>): Class {
    const instance = new Class();
    Object.assign(instance, obj);
    return instance;
  }
}

在Service中调用该静态方法:

async getById(id: string): Promise<Class> {
    try {
      const { data } = await backend.get(`/${id}`);
      return Class.from(data);
    } catch (err) {
      throw new Error(err.response.data.message);
  }
}

注意事项

  • 不要依赖TypeScript的类型断言来“伪装”实例类型,类型断言仅作用于编译时检查,不会改变运行时对象的本质。
  • 如果Class包含嵌套的自定义类对象,Object.assign只会做浅拷贝,需要在构造函数或from方法中手动处理嵌套对象的实例化。

内容的提问来源于stack exchange,提问作者Lucas Pedroso Santos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:50:26