TypeScript自定义泛型ToggleStatus赋值与索引报错及泛型失效问题
问题根源与修正方案
原代码的核心问题有两处:
ToggleStatus类型定义中,Extract<T, string>是错误用法——T是StatusProps的子类型(对象类型),要获取它的键名应该用keyof T,而非Extract。- 空对象初始化时无法满足
ToggleStatus<T>的完整类型要求;Object.keys返回的是string类型,无法与ToggleStatus<T>的键名类型匹配,导致索引报错。
修正后的完整代码
type StatusProps = { [key: string]: React.JSX.Element; } // 修正类型定义:用keyof T获取对象键名,生成toggle开头的方法名 type ToggleStatus<T extends StatusProps> = { [K in keyof T as `toggle${Capitalize<string & K>}`]: () => void; } // 示例:假设props.status的具体类型(替换为你实际的类型) type DemoStatus = { active: React.JSX.Element; disabled: React.JSX.Element; }; const props = { status: {} as DemoStatus }; // 1. 先用Partial允许空对象初始化,逐步填充方法 const toggleStatus: Partial<ToggleStatus<DemoStatus>> = {}; // 2. 将Object.keys返回的key断言为keyof T,让TypeScript识别具体键名 Object.keys(props.status).forEach((key) => { const typedKey = key as keyof DemoStatus; const methodName = `toggle${Capitalize<string & typedKey>}` as const; toggleStatus[methodName] = () => { // 这里写入你的业务逻辑 }; }); // 3. 断言为完整类型(确保循环已覆盖所有键) const finalToggleStatus = toggleStatus as ToggleStatus<DemoStatus>;
关键修正说明
keyof T替代Extract<T, string>:正确获取泛型对象的键名集合。Capitalize<string & K>:过滤掉keyof T可能包含的symbol类型,只处理字符串键名。Partial<ToggleStatus<T>>:允许初始为空对象,避免初始化时的类型不匹配错误。key as keyof T:解决Object.keys返回string导致的索引类型不兼容问题。
更简洁的函数封装方案
如果不想手动处理类型断言,可通过函数封装让TypeScript自动推导类型:
function createToggleStatus<T extends StatusProps>(status: T): ToggleStatus<T> { const toggleStatus = {} as ToggleStatus<T>; (Object.keys(status) as Array<keyof T>).forEach((key) => { const methodName = `toggle${Capitalize<string & key>}` as keyof ToggleStatus<T>; toggleStatus[methodName] = () => { // 业务逻辑实现 }; }); return toggleStatus; } // 使用示例 const toggleStatus = createToggleStatus(props.status);
内容的提问来源于stack exchange,提问作者BrandenXia
相关产品推荐
相关产品推荐

