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

如何在React自定义useModel Hook中通过TypeScript根据Key动态推导对应Value的类型?

解决方案:让useModel的handleChange根据key动态校验value类型

当然可以实现这个需求!问题出在你当前的HandleModelChangeFn类型定义上——它把value的类型设为了T所有属性值的联合类型,导致TypeScript无法根据传入的具体key来锁定对应的value类型。我们只需要把这个函数类型改成泛型函数,就能让TypeScript在调用时自动推断出对应键的value类型。

修改步骤:

  1. 更新HandleModelChangeFn类型定义
    把原来的类型改成泛型函数,新增一个泛型参数K来代表具体的键(必须是T的键),这样value的类型就可以精确绑定为T[K]:

    export type HandleModelChangeFn<T> = <K extends keyof T>(key: K, value: T[K]) => void;
    
  2. 调整handleChange函数的实现
    让handleChange函数也符合这个泛型类型,确保调用时TypeScript能正确推断K:

    const handleChange = useCallback(<K extends keyof T>(key: K, value: T[K]) => {
      setModel((prevState) => ({
        ...prevState,
        [key]: value,
      }));
    }, []);
    

修改后的完整代码:

import { Dispatch, SetStateAction, useCallback, useState } from 'react';

export type HandleModelChangeFn<T> = <K extends keyof T>(key: K, value: T[K]) => void;

const useModel = <T>(initialModel: T): [T, HandleModelChangeFn<T>, Dispatch<SetStateAction<T>>] => {
  const [model, setModel] = useState<T>(initialModel);

  const handleChange = useCallback(<K extends keyof T>(key: K, value: T[K]) => {
    setModel((prevState) => ({
      ...prevState,
      [key]: value,
    }));
  }, []);

  return [model, handleChange, setModel];
};

export default useModel;

效果验证:

现在当你像之前那样调用:

interface User {
  name: string;
  age: number;
}
const initialModel: User = { name: '', age: 1 }
const [model, handleModelChange] = useModel(initialModel);
handleModelChange('age', 'John'); // TypeScript会直接报错:类型"string"不能赋值给类型"number"

TypeScript会立刻识别出类型不匹配,完美实现了你想要的动态类型校验效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:27:47