TypeScript如何返回子类类型?避免类型转换并保留智能提示
解决TypeScript中Entity子类get方法自动返回对应类型的问题
问题场景
原来的实现中,Entity类的get方法无法自动推断子类对应属性的类型,必须手动用as转换,示例代码:
class Entity { constructor(public data: Record<string, any>) {} get(key: string) { return this.data[key]; } } class User extends Entity { constructor(data: { name: string; age: number }) { super(data); } } // 必须手动转换类型,无智能提示 const user = new User({ name: "Alice", age: 30 }); const userName = user.get("name") as string;
解决方案:使用泛型约束与索引类型
通过给Entity类添加泛型参数,并结合keyof索引类型,让get方法自动推断返回值类型,同时保留智能提示:
基础实现代码
// 定义泛型Entity类,T约束为键值对类型 class Entity<T extends Record<string, any>> { constructor(public data: T) {} // K限定为T的键,返回值类型为T对应键的类型 get<K extends keyof T>(key: K): T[K] { return this.data[key]; } } // 子类继承时传入自身的数据类型 class User extends Entity<{ name: string; age: number }> { constructor(data: { name: string; age: number }) { super(data); } // 内部使用get方法时自动推断类型 printUserInfo() { console.log(`Name: ${this.get("name")}, Age: ${this.get("age")}`); } } // 使用示例:无需手动转换,有智能提示 const user = new User({ name: "Bob", age: 25 }); const userName = user.get("name"); // 自动推断为string const userAge = user.get("age"); // 自动推断为number // user.get("invalidKey"); // 编译报错,提示不存在该键
优化方案:抽离数据接口
如果数据结构复杂或需要复用,可将数据类型抽离为接口,提升代码可维护性:
interface UserData { name: string; age: number; email: string; } class Entity<T extends Record<string, any>> { constructor(public data: T) {} get<K extends keyof T>(key: K): T[K] { return this.data[key]; } } class User extends Entity<UserData> { constructor(data: UserData) { super(data); } sendEmail() { console.log(`Sending email to ${this.get("email")}`); } }
原理说明
- 泛型参数
T约束了data的结构,让TypeScript知晓数据的具体键值类型 K extends keyof T限定get方法的参数必须是T中存在的键,提供智能提示并拦截无效键- 返回值
T[K]让TypeScript自动推断对应键的属性类型,无需手动转换
内容的提问来源于stack exchange,提问作者DiDi
相关产品推荐
相关产品推荐

