Typescript默认的类属性getter

时间:2018-01-24 18:42:29

标签: typescript generics getter

假设我有一个具有内部私有属性的类:

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,所以当使用更结构化的类时,我可以访问任何字段而无需编写单独的get。

console.log(A.field2);

field2不是定义的getter,但我希望能够在类中执行以下操作:

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。然后,这也可以扩展到更复杂的结构。

1 个答案:

答案 0 :(得分:5)

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

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

    }
}

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

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() { }
}

如果您不介意一些复杂的语法并且只是声明属性,那么您也可以访问from 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);