TypeScript如何限定动态赋值的类属性排除getter与实例方法
解决方案
实现思路
- 先通过工具类型过滤掉所有实例方法对应的键
- 再通过类型对比过滤掉所有只读的getter属性对应的键
- 将
updateProperty改为泛型方法,自动匹配传入属性对应的value类型,避免类型不匹配报错
完整工具类型代码
// 判断两个类型是否严格相等 type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? A : B; // 筛选出类型中所有非函数属性的键 type NonMethodKeys<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T] // 筛选出类型中所有可写属性的键(排除getter只读属性) type WritableKeys<T> = { [K in keyof T]: IfEquals<{ [P in K]: T[P] }, { -readonly [P in K]: T[P] }, K, never> }[keyof T] // 最终可设置属性的键:非方法+可写 type SettableKeys<T> = NonMethodKeys<T> & WritableKeys<T>
注意:如果你的类中存在
e: Function这类函数类型的可写实例属性需要支持更新,可将NonMethodKeys替换为手动排除实例方法键的写法:type NonMethodKeys<T> = Exclude<keyof T, 'updateProperty'>按你的实际类的方法名补充排除项即可。
修改后的类代码
type AnotherType = {}; class Foo { a: number; b: number; c: string; d: AnotherType; e: Function; constructor(a: number, b: number) { this.a = a; this.b = b; } get sum(): number { return this.a + this.b; } get name(): string { return `My name is ${this.c}`; } // 修改为泛型方法 public updateProperty<K extends SettableKeys<Foo>>( prop: K, value: Foo[K], ) { this[prop] = value; } }
效果验证
调用时不会再出现之前的报错,且有完整的类型校验:
const foo = new Foo(1,2); foo.updateProperty('a', 3); // 正常编译 foo.updateProperty('c', 'test'); // 正常编译 foo.updateProperty('sum', 10); // 编译报错,sum不在允许的prop范围内 foo.updateProperty('updateProperty', ()=>{}); // 编译报错,方法属性被过滤
内容的提问来源于stack exchange,提问作者IAmJulianAcosta
相关产品推荐
相关产品推荐

