TypeScript泛型convertDates方法出现类型不匹配无法赋值错误
报错原因
两个报错都是TypeScript的静态类型校验触发的:
- 你定义的泛型默认是输入类型和返回类型完全一致,你将原本为字符串类型的属性赋值为Date类型,自然触发类型不匹配的报错
- TypeScript对动态索引访问的属性
input[key]无法自动做类型收窄,哪怕你加了typeof input[key] === 'string'的判断,TS还是不能识别该值为字符串类型,所以调用正则test方法时报错
修复方案
简易修复(适合内部工具方法,逻辑可保证正确的场景)
// 给泛型增加对象类型约束,避免传入非对象参数 private convertDates<T extends Record<string, any>>(input: T): T { for (const key in input) { if (!input.hasOwnProperty(key)) { continue; } // 将索引值存入临时变量,TS可对变量正常做类型收窄 const curValue = input[key]; // 补充null判断,typeof null 也会返回object,避免递归null报错 if (typeof curValue === 'object' && curValue !== null) { this.convertDates(curValue); } else if (typeof curValue === 'string' && this.MY_REGEXP.test(curValue)) { // 类型断言告知TS此处明确允许修改属性类型为Date input[key] = new Date(curValue) as T[Extract<keyof T, string>]; } } return input; }
类型严谨版修复
如果希望方法返回的类型能正确识别到日期属性已经被转为Date类型,可以先定义递归转换类型,再修改方法定义:
// 递归转换类型:将所有字符串属性转为 string | Date,嵌套对象同步转换 type DateConverted<T> = { [K in keyof T]: T[K] extends string ? string | Date : T[K] extends object ? DateConverted<T[K]> : T[K] } private convertDates<T extends Record<string, any>>(input: T): DateConverted<T> { for (const key in input) { if (!input.hasOwnProperty(key)) { continue; } const curValue = input[key]; if (typeof curValue === 'object' && curValue !== null) { input[key] = this.convertDates(curValue) as T[Extract<keyof T, string>]; } else if (typeof curValue === 'string' && this.MY_REGEXP.test(curValue)) { input[key] = new Date(curValue) as T[Extract<keyof T, string>]; } } return input as DateConverted<T>; }
修改后调用方法返回的DTO会自动识别属性可能为Date类型,后续使用不需要额外做类型断言。
内容的提问来源于stack exchange,提问作者dorcsi
相关产品推荐
相关产品推荐

