You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 22:06:04