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

如何让TypeScript编译器识别动态生成的getter与setter?

解决方案

方案1:显式声明属性(简单直接,适合属性固定的场景)

直接在类中用declare关键字提前声明所有动态生成的属性类型即可,declare仅做类型标注,不会生成实际JS代码,不影响原有运行逻辑。

class ColorPalette {
    // 提前声明动态生成的属性
    declare foregroundColor: string;
    declare backgroundColor: string;
    declare borderColor: string;

    #colors = [
        ["foregroundColor", "#cccccc"], 
        ["backgroundColor", "#333333"], 
        ["borderColor", "#aaaaaa"]
    ] as const; 

    constructor() {
        this.#colors.forEach((e, i) => {
            Object.defineProperty(this, this.#colors[i][0], {
                enumerable: true,
                get() { return this.#colors[i][1]; },
                set(hex: string) { 
                    if (/^#[0-9a-f]{6}$/i.test(hex)) { 
                        this.#colors[i][1] = hex;
                    }
                }
            })
        });
    }

    toString(): string {
        return Object.values(this).map(c => c.toString().toUpperCase()).join(", ");
    }
}

let redPalette = new ColorPalette();
redPalette.foregroundColor = "#ff0000"; // 不再报错,且会校验类型为字符串
console.log(redPalette.foregroundColor); // 类型提示正常

方案2:统一维护属性列表(避免重复定义,适合属性频繁迭代的场景)

如果希望只修改一处属性列表就能同步更新类型,避免后续属性增减时两边修改出现不一致,可以先定义属性key的元组,再通过映射类型批量生成类的属性声明:

// 统一定义所有颜色key,修改只需改这一处
const COLOR_KEYS = ["foregroundColor", "backgroundColor", "borderColor"] as const;
type ColorKey = typeof COLOR_KEYS[number];
// 生成属性映射类型
type ColorPaletteProps = {
    [key in ColorKey]: string;
}

class ColorPalette implements ColorPaletteProps {
    // 批量声明所有动态属性
    declare [key in ColorKey]: string;

    #colors: [ColorKey, string][] = [
        ["foregroundColor", "#cccccc"], 
        ["backgroundColor", "#333333"], 
        ["borderColor", "#aaaaaa"]
    ]; 

    constructor() {
        this.#colors.forEach((e, i) => {
            Object.defineProperty(this, this.#colors[i][0], {
                enumerable: true,
                get() { return this.#colors[i][1]; },
                set(hex: string) { 
                    if (/^#[0-9a-f]{6}$/i.test(hex)) { 
                        this.#colors[i][1] = hex;
                    }
                }
            })
        });
    }

    toString(): string {
        return Object.values(this).map(c => c.toString().toUpperCase()).join(", ");
    }
}

let redPalette = new ColorPalette();
redPalette.foregroundColor = "#ff0000"; // 类型校验正常
// 拼写错误会直接编译报错,比如redPalette.foregroundColr = "#ff0000" 会提示属性不存在
console.log(redPalette.toString());

原理解释

TypeScript是静态类型检查工具,无法感知运行时通过Object.defineProperty动态挂载的属性,所以需要我们通过类型声明提前告知TS这些属性的存在和类型,既不会影响原有JS运行逻辑,还能获得完整的编译时校验和编辑器类型提示。

内容的提问来源于stack exchange,提问作者a5hk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:06:02