TypeScript类重构:如何定义对应类属性的方法参数类型
重构Card类的重复Getter逻辑,实现类型安全的通用方法
嘿,我明白你想把重复的懒加载逻辑提取成通用方法,还想保证类型安全的需求!TypeScript的泛型和keyof关键字刚好能完美解决这个问题,咱们一步步来重构:
首先,核心目标是让通用方法既能正确识别类的属性,又能匹配属性和getter的类型,避免出现any导致的类型丢失。
步骤1:定义带泛型的Getter类型
先把FieldValueGetter改成带返回值泛型的类型,这样能和目标属性的类型绑定起来:
type FieldValueGetter<V> = (data: Data, user: User) => V;
步骤2:实现类型安全的getFieldValue方法
用keyof Card约束属性名的范围,再通过泛型T关联属性的类型,让TypeScript自动帮我们做类型检查:
private getFieldValue<T extends keyof Card>( getter: FieldValueGetter<Card[T]>, fieldName: T ): Card[T] { if (!this[fieldName]) { this[fieldName] = getter(this.data, this.user); } return this[fieldName]; }
T extends keyof Card:确保fieldName是Card类的有效属性名,彻底避免拼写错误。FieldValueGetter<Card[T]>:强制getter的返回值类型必须和目标属性的类型完全匹配,比如给nameVal(string类型)传的getter必须返回string。- 返回值
Card[T]:让调用方能直接拿到正确的属性类型,不需要额外的类型断言。
步骤3:简化原有Getter
现在原来的name和address getter可以直接调用通用方法,代码瞬间简洁很多:
get name(): string { return this.getFieldValue(name_getter, 'nameVal'); } get address(): string[] { return this.getFieldValue(address_getter, 'addressVal'); }
完整重构后的代码
// 先补充你的Data和User类型定义(根据实际情况修改) type Data = { firstName: string; street: string; city: string; }; type User = { lastName: string; country: string; }; type FieldValueGetter<V> = (data: Data, user: User) => V; class Card { protected readonly data: Data; protected readonly user: User; nameVal: string; addressVal: string[]; constructor(raw_data: Data, user: User) { this.data = raw_data; this.user = user; } private getFieldValue<T extends keyof Card>( getter: FieldValueGetter<Card[T]>, fieldName: T ): Card[T] { if (!this[fieldName]) { this[fieldName] = getter(this.data, this.user); } return this[fieldName]; } get name(): string { return this.getFieldValue(name_getter, 'nameVal'); } get address(): string[] { return this.getFieldValue(address_getter, 'addressVal'); } } // 示例getter函数(替换成你自己的业务逻辑) function name_getter(data: Data, user: User): string { return `${data.firstName} ${user.lastName}`; } function address_getter(data: Data, user: User): string[] { return [data.street, data.city, user.country]; }
额外小提示
- 把
getFieldValue设为private是因为它是内部复用的逻辑,不需要对外暴露,符合封装原则。 - 这种方式完全保留了类型安全:如果不小心给
nameVal传了一个返回number的getter,TypeScript会直接抛出错误,提前规避运行时的类型问题。
内容的提问来源于stack exchange,提问作者PBandJ
相关产品推荐
相关产品推荐

