Typescript 默认的 getter 个属性,共 class 个属性

Typescript default getter of class properties

假设我有一个 class 内部私有属性:

export class foo {
    private bar_:string;
    private baz_:number;
    constructor() { }

我知道我可以通过为变量写一个 getter 来从 bar 和 baz 获取值。

    get bar():string {
        return this.bar_;
    }
    get baz():number {
        return this.baz_;
    }

这样我就可以使用以下方式访问数据:

let A:foo = new foo();
console.log(foo.baz);

有没有办法拥有一个简单的泛型 getter,因此在使用更结构化的 class 时,我可以访问任何字段而无需编写单独的 get。

console.log(A.field2);

field2 未定义 getter,但我希望能够在 class:

中执行类似以下操作
export class foo {
    private bar_:string;
    private baz_:number;
    private field2_:string;
    constructor() { }

    get X():any {        // X here is some placeholder that could be used, which contains the field name being asked (bar_, baz_, etc.)
        return this.X;       // This would assume that a field is the same name as what was passed.
    }

在 HTML 或其他区域,我可以访问 A.bar_ 的值,这将允许我保护私有变量,但无需编写 getter 每个字段。这也可以扩展到更复杂的结构。

如果您希望属性为只读并且您可以在构造函数中设置它们,您可以使用 readonly 修饰符:

export class foo {
    constructor(
        public readonly bar:string,
        public readonly baz:number,
        public readonly field2:string) { 

    }
}

如果您只想从 HTML 模板访问 属性,您可以使用装饰器来创建吸气剂,但它们不会出现在类型上:

function createGetter (target: any, key: string) {
    let propName = key.substr(0, key.length - 1);
    Object.defineProperty(target, propName, {
        get: function() {
            return this[key]
        }
    });
}


export class foo {
    @createGetter private bar_:string;
    @createGetter private baz_:number = 10;
    @createGetter private field2_:string;
    constructor() { }
}

如果您不介意一些复杂的语法并且只是声明属性,您也可以从 typescript 访问:

function withGetters<TProps>() {
    return <TBase>(cls: new () => TBase) : new () => TProps & TBase => {
        return <any>cls;
    };
}
class baseFoo {
    @createGetter private bar_:string;
    @createGetter private baz_:number = 10;
    @createGetter private field2_:string;
    constructor()  { }
}
export const foo = withGetters<{ 
    readonly bar: string;
    readonly baz: number; 
    readonly field2: string; 
}>()(baseFoo);