TypeScript如何通过匹配键名修改属性类型,将后缀At的字段转为Date类型
解决方案
1. 实现通用字段转换工具类型
利用TypeScript 4.1+支持的模板字面量类型和映射类型,构造可以自动识别At后缀字段的工具类型:
type NormalizeAtFields<T> = { // 遍历对象所有键,匹配后缀为At的键则替换类型为Date,否则保留原类型 [K in keyof T]: K extends `${string}At` ? Date : T[K]; };
2. 标注函数返回值类型
给你的normalizeUser函数显式标注返回值类型,同时补充类型断言对齐运行时逻辑和TS类型推导:
type UserRaw = { name: string; createdAt: string; }; const normalizeUser = function (attributes: UserRaw): NormalizeAtFields<UserRaw> { const normalized = { ...attributes }; Object.entries(normalized).forEach(([key, value]) => { if (key.endsWith('At')) { (normalized as any)[key] = new Date(value as any); } }); // 显式断言返回值匹配我们定义的类型 return normalized as NormalizeAtFields<UserRaw>; } export type User = ReturnType<typeof normalizeUser>; // 此时推导的User类型完全符合预期: // { // name: string; // createdAt: Date; // }
3. 通用版本封装(可选)
如果你需要在多个对象上复用这个转换逻辑,可以封装成泛型工具函数,所有传入的对象都会自动转换At后缀字段的类型:
function normalizeWithAtDates<T extends Record<string, any>>(raw: T): NormalizeAtFields<T> { const normalized = { ...raw }; Object.entries(normalized).forEach(([key, value]) => { if (key.endsWith('At')) { (normalized as any)[key] = new Date(value as any); } }); return normalized as NormalizeAtFields<T>; } // 使用示例 const normalizeUser = (raw: UserRaw) => normalizeWithAtDates(raw); const normalizeOrder = (raw: {id: number; payAt: string}) => normalizeWithAtDates(raw);
递归处理嵌套对象(可选)
如果你的对象存在嵌套结构,也需要处理内部的At后缀字段,可以扩展工具类型为递归版本:
type NormalizeAtFieldsRecursive<T> = { [K in keyof T]: K extends `${string}At` ? Date : T[K] extends Record<string, any> ? NormalizeAtFieldsRecursive<T[K]> : T[K] }
内容的提问来源于stack exchange,提问作者Martin Malinda
相关产品推荐
相关产品推荐

