打字稿中 getter 和 setter 的“计算属性名称”

时间:2021-01-04 01:28:39

标签: javascript typescript

Javascript 有语法

class C {
   get [prop]() { ... }
   set [prop](v) { ... }
}

用于获取或设置任意属性。

有没有办法在 Typescript 中做到这一点?

1 个答案:

答案 0 :(得分:1)

即使在 JavaScript 中,您的示例代码实际上也没有执行您想要执行的操作。 Computed property names 通过评估表达式来得出属性名称。例如:

const computed = {
    ["foo".toUpperCase()]: "bar"
}
console.log(computed.FOO) // bar

除非 prop 已经是一个现有变量,否则使用 prop 作为计算属性将失败。每个计算属性将仅用作单个属性,而不是所有可能的属性。


我认为在 JavaScript 中(因此在 TypeScript 中)拦截 all 属性获取和设置的唯一方法是使用 Proxy。这是一种可能的实现:

class C {
    [k: string]: any;
    constructor() {
        return new Proxy<C>(this, {
            get(thiz, prop) {
                console.log(`getting ${String(prop)}`);
            },
            set(thiz, prop, v) {
                console.log(`setting ${String(prop)} to ${v}`);
                return true;             }
        });
    }
}

我们告诉 TypeScript,类 C 的实例有一个 string index signature,这样它就可以接受任何属性键(和 any 属性值)。然后,constructor() 方法显式返回一个 Proxy,这样当您在它上面call the new operator 时,您将获得代理而不是默认的 this

无论如何,代理实现了 get handlerset handler,因此它拦截所有属性的所有获取和设置。属性键名称被传递到处理程序方法中,因此您实际上可以获得您正在寻找的行为:

const c = new C();
c.foo; // getting foo
c.foo = "bar"; // setting foo to bar

注意:我建议您在生产环境中使用之前非常小心并测试上述任何代码;在类构造函数中返回自定义对象或显示的特定 Proxy 处理程序很可能涉及边缘情况。

Playground link to code

相关问题