TypeScript如何通过构造函数推导类型,避免重复指定键名?
TypeScript 简化FilterEqual类的泛型参数写法
现有如下代码:
class User { public name: string public age: number } class FilterEqual<T, K extends keyof T> { constructor(field: K, public value: T[K]) {} } new FilterEqual<User, 'name'>('name', '')
这段代码能实现严格的类型校验:field必须是User的键之一,value的类型必须和所选键的类型匹配,错误用法会直接报错:
new FilterEqual<User, 'invent'>('invent', '') // 字段不存在,报错 new FilterEqual<User, 'name'>('name', 1) // 类型不匹配,报错
但这种写法需要重复指定键名(既要在泛型参数里写'name',又要在构造函数参数里传'name'),能不能简化成只传入User泛型的写法?比如:
new FilterEqual<User>('name', '')
我尝试过把类的泛型简化成只保留T,但这样会失去类型校验的严格性,允许错误的实例创建:
class FilterEqual<T> { constructor(field: keyof T, public value: T[keyof T]) {} } // 这种写法不会报错,但明显不符合预期 new FilterEqual<User>('name', 1)
解决方案
将泛型K从类的泛型参数移到构造函数的泛型参数中,让TypeScript自动推导K的类型:
class User { public name: string public age: number } class FilterEqual<T> { constructor<K extends keyof T>(field: K, public value: T[K]) {} } // 正确用法,无需重复指定键名 new FilterEqual<User>('name', '') new FilterEqual<User>('age', 25) // 错误用法依旧会触发类型报错 new FilterEqual<User>('invent', '') // 字段不存在,报错 new FilterEqual<User>('name', 1) // 类型不匹配,报错
原理说明
把K作为构造函数的泛型参数后,TypeScript会根据你传入的field参数自动推导出K的具体值,同时约束value的类型必须严格匹配T[K],既保留了原始代码的类型校验能力,又省去了重复指定键名的冗余操作。
内容的提问来源于stack exchange,提问作者srhuevo
相关产品推荐
相关产品推荐

