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

TypeScript自定义useUpdate Hook泛型类型声明报错咨询

问题说明

自定义Hook useUpdate 初始实现如下,泛型推导存在优先级问题:

import { useRef, useEffect } from 'react';

type CallBack<T extends readonly any[]> = (
  ...args: T
) => void | (() => void | undefined);

function useUpdate<T extends readonly any[]>(
  callback: CallBack<T>,
  deps: T
) {
  const didMount = useRef(false);
  const prevDeps = useRef(deps);

  useEffect(() => {
    if (!didMount.current) {
      didMount.current = true;
      return;
    }

    const clean = callback(...prevDeps.current);
    prevDeps.current = deps;

    return () => {
      if (clean) clean();
    };
  }, deps);
}

使用时回调声明入参的场景校验正常,无入参回调会触发类型错误:

const state: boolean = useSomethingElse();

// 正常运行无类型报错
useUpdate((prevState) => {
 console.log('对比前后状态', prevState, state);
},[state]);

// 触发类型报错
useUpdate(() => {
 console.log('仅感知状态更新', state);
},[state]);
// 报错信息:Argument of type '[boolean]' is not assignable to parameter of type '[]'.
// Source has 1 element(s) but target allows only 0.ts(2345)

问题核心原因:TypeScript默认会从所有匹配泛型的参数位置推导类型,回调无入参时会优先将泛型T推导为空元组[],和实际传入的deps类型冲突。

解决方案

通过NoInfer类型工具阻断回调参数位置的泛型推导,让TS仅从deps参数位置推导泛型T即可。

  • TS 5.4及以上版本可直接使用内置NoInfer工具类型
  • 低版本TS可自行实现等效类型:type NoInfer<T> = T extends infer U ? U : never

修改后的类型定义(内部逻辑无需调整):

// 低版本TS放开下面注释即可
// type NoInfer<T> = T extends infer U ? U : never;

type CallBack<T extends readonly any[]> = (
  ...args: NoInfer<T> // 阻断该位置的泛型推导优先级
) => void | (() => void | undefined);

function useUpdate<T extends readonly any[]>(
  callback: CallBack<T>,
  deps: T
) {
  const didMount = useRef(false);
  const prevDeps = useRef(deps);

  useEffect(() => {
    if (!didMount.current) {
      didMount.current = true;
      return;
    }

    const clean = callback(...prevDeps.current);
    prevDeps.current = deps;

    return () => {
      if (clean) clean();
    };
  }, deps);
}

修改后类型表现完全符合预期:

  • 泛型T始终以传入的deps类型为准,不会被无参回调推导为空元组
  • 回调入参的类型校验依然生效,如果声明的入参类型和deps类型不匹配,会正常抛出类型错误
  • 无参回调场景不再触发误报

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:45:43