TypeScript decode_json函数报TS2322泛型错误如何修复?
错误原因
- 泛型声明逻辑错误:原函数声明输入类型为
T1时返回值也为T1,但实际处理后对象的键名、数组内元素类型均发生了变更,和输入的原始类型并不匹配,触发TS的类型校验报错。 - 未处理null边界情况:
typeof null返回值为object,如果输入包含null值会被误判为普通对象处理,引发运行时错误。 - 缺少必要的类型断言:TS无法自动推导递归处理后的复杂结构类型,需要手动通过类型断言告知编译器返回值符合预期类型。
修复方案
最小复现示例修复(addBlabla函数)
首先定义递归映射类型描述处理后的结构,再调整函数的泛型声明,补充类型断言:
// 递归类型:描述添加blabla后缀后的返回值结构 type DeepAddBlabla<T> = T extends Array<infer U> ? Array<DeepAddBlabla<U>> : T extends object ? Record<string, DeepAddBlabla<T[keyof T]>> : T; function addBlabla<T>(json: T): DeepAddBlabla<T> { // 处理数组 if (Array.isArray(json)) { return json.map(addBlabla) as DeepAddBlabla<T>; } // 处理非null对象 if (typeof json === "object" && json !== null) { return Object.entries(json).reduce((acc, [key, value]) => { acc[`${key}blabla`] = addBlabla(value); return acc; }, {} as Record<string, any>) as DeepAddBlabla<T>; } // 原始类型直接返回 return json as DeepAddBlabla<T>; }
完整decode_json函数修复
如果需要更精准的类型提示,可以把键名映射做成字面量类型,自动推导返回值的键名:
const alphabet = 'abcdefghijklmnopqrstuvwxyz' as const; const keys = ['latitude', 'longitude'] as const; // 键名映射类型 type KeyMap = { [K in typeof alphabet[number]]: typeof keys[typeof alphabet.indexOf(K)] }; // 递归解码类型 type DecodeJson<T> = T extends Array<infer U> ? Array<DecodeJson<U>> : T extends object ? { [K in keyof T as K extends keyof KeyMap ? KeyMap[K] : never]: DecodeJson<T[K]> } : T; export default function decode_json<T>(json: T): DecodeJson<T> { if (Array.isArray(json)) { return json.map(decode_json) as DecodeJson<T>; } if (typeof json === 'object' && json !== null) { return Object.entries(json).reduce((acc, [key, value]) => { acc[decodeKey(key)] = decode_json(value); return acc; }, {} as Record<string, any>) as DecodeJson<T>; } return json as DecodeJson<T>; } function decodeKey(key: string): string { const index = alphabet.indexOf(key); if (index !== -1 && index < keys.length) return keys[index]; throw new Error(`The key "${key}" does not exist.`); }
内容的提问来源于stack exchange,提问作者Altaula
相关产品推荐
相关产品推荐

