【问题标题】:Typescript: simulating nested classes + private member access打字稿:模拟嵌套类+私有成员访问
【发布时间】:2016-08-21 06:38:25
【问题描述】:

过去发布的关于打字稿和嵌套类的答案建议使用该语言的声明合并功能。我已经用下面的示例进行了尝试,它按预期执行,但会生成编译器消息:

foo.ts(9,37): error TS2341: Property '_bar' is private and only accessible
              within class 'Foo'.

...这似乎很奇怪,因为正如所写,Class Bletch 是 Foo 的成员。

是否有一种最佳实践方法来抑制有关访问外部类的私有成员的错误?(我知道我可以将this._foo 替换为(this._foo as any) ,但似乎应该有更优雅的方式......)

例子:

export class Foo {
    constructor( private _bar: number ){}
    //...
}

export module Foo {
    export class Bletch {
        constructor( private _foo: Foo ) {}
        barf(): number { return this._foo._bar; }
    }
}

let a = new Foo(57);
let b = new Foo.Bletch(a)

console.log(b.barf());

【问题讨论】:

    标签: typescript nested


    【解决方案1】:

    成为类的成员不允许您访问其私有成员/方法,但通常内部类可以。
    在这种情况下虽然你并没有真正的内部类,你只需将类Bletch添加为类Foo的属性,在编译的js中更容易看到:

    var Foo = (function () {
        function Foo(_bar) {
            this._bar = _bar;
        }
        return Foo;
    }());
    var Foo;
    (function (Foo) {
        var Bletch = (function () {
            function Bletch(_foo) {
                this._foo = _foo;
            }
            Bletch.prototype.barf = function () { return this._foo._bar; };
            return Bletch;
        }());
        Foo.Bletch = Bletch;
    })(Foo || (Foo = {}));
    

    您可以通过执行以下操作来解决此问题:

    module Foo {
        interface Instance {
            _bar: number;
        }
    
        export class Bletch {
            private _foo: Instance;
    
            constructor( foo: Instance | Foo ) {
                this._foo = foo as Instance;
            }
    
            barf(): number { return this._foo._bar; }
        }
    }
    

    (code in playground)

    您还有另一种定义“内部类”的方法:

    interface Instance {
        _bar: number;
    }
    
    class Foo {
        constructor( private _bar: number ) {}
    
        static Bletch = class {
            private _foo: Instance;
    
            constructor( foo: Instance | Foo ) {
                this._foo = foo as Instance;
            }
    
            barf(): number { return this._foo._bar; }
        }
    }
    

    (code in playground)

    这看起来更像是通常的做法,而且更短一些。

    【讨论】:

    • 好的,所以定义一个与朋友可访问的成员的接口,对吧?
    • 我喜欢你的最后一个例子,尽管声明 Bletch 类的语法似乎有点强制。我发现的唯一缺点是 Bletch 似乎被 VS Code IntelliSense 标记为“匿名类”。
    • P.S.我建议对您的示例代码进行微调,去掉一个额外的私有属性。
    • 发现了接口方法的另一个缺点:如果在类Foo 和接口Instance 中声明的成员名称不同,则不会生成编译时错误。类型安全的部分损失......
    • 是的,因为你想让Foo的成员是私有的,所以你不能实现Instance接口,从而保持类型安全。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多