在 TypeScript 中访问外部 class 的成员

Access members of outer class in TypeScript

从 TypeScript 1.6 开始,我们可以使用 . In other OOP-centric languages like Java, inner classes can access members of the outer class, even private ones.

轻松创建内部 类

此行为类似于闭包的概念,其中函数可以从定义它的范围访问变量。

为什么我不能在 TypeScript 中实现这个? ECMAScript 2015 中的 类 规范在这里起作用吗?

呈现预期行为的代码:

class OuterClass {
    private outerField = 1337;

    public InnerClass = class { 
        public accessOuter() {
            return this.outerField; // outerField not defined
        }
    }
}

var outer = new OuterClass();
var inner = new outer.InnerClass();
var win = inner.accessOuter();

如果查看代码的编译 java 脚本,就更容易理解为什么不能这样做:

var OuterClass = (function () {
    function OuterClass() {
        this.outerField = 1337;
        this.InnerClass = (function () {
            function class_1() {
            }
            class_1.prototype.accessOuter = function () {
                return this.outerField; // outerField not defined
            };
            return class_1;
        }());
    }
    return OuterClass;
}());

如您所见,outerField 被定义为 OuterClass 的成员,如下所示:

this.outerField = 1337;

当您尝试在 InnerClass 中访问它时,您会:

return this.outerField;

但是这里的thisclass_1的实例而不是OuterClass所以this中没有outerField
此外,您无法从内部 class 访问外部 class.

的实例

java中的解决方法是这样的:

class OuterClass {
    private int outerField = 1337;

    public class InnerClass {
        public int accessOuter() {
            return OuterClass.this.outerField;
        }
    }
}

但是 typescript/javascript 中没有 OuterClass.this.outerField 的等价物。
查看打字稿内部 classes 更像是 java 中的静态内部 classes,但在这里你也只能访问 public 属性:

class OuterClass {
    public static outerField = 1337; // has to be public

    public InnerClass = class { 
        public accessOuter() {
            return OuterClass.outerField;
        }
    }
}

您可以将外部 class 的实例传递给内部 class:

class OuterClass {
    public outerField = 1337;

    public InnerClass = class {
        constructor(private parent: OuterClass) {}

        public accessOuter() {
            return this.parent.outerField;
        }
    }
}

但同样,您需要 outerField public.


编辑

如果你想实现一些模拟所需行为的东西(也就是说,内部 class 实例将可以访问私有外部 class 成员),那么你可以做一些事情像这样:

interface OuterClassProxy {
    outerField: number;
}

interface IInnerClass {}

class OuterClass {
    private outerField = 1337;

    static InnerClass = class implements IInnerClass {
        constructor(private parent: OuterClassProxy) {}

        public accessOuter() {
            return this.parent.outerField;
        }
    }

    public createInnerClass(): IInnerClass {
        let outerClassInstance = this;

        return new OuterClass.InnerClass({
            get outerField(): number {
                return outerClassInstance.outerField;
            },
            set outerField(value: number) {
                outerClassInstance.outerField = value;
            }
        });
    }
}

这是一项相当多的工作,但它会完成的。

@Nitzan 的回答很棒。我只是想补充一点,我最近想到了这个,也许它有帮助:

class Outer {

    constructor() {
        this.val = 1337;
    }

    get Inner() {
        let Outer = this;
        return class {
            accessVal() { return Outer.val; }
        }
    }

}

new (new Outer()).Inner().accessVal(); // 1337

以下是在 Typescript 中执行此操作的正确方法:

class OuterClass {
  private outerField = 1337;

  get InnerClass() {
    const thatOuterField = this.outerField // <-- Notice this addition
    return   class {
      public accessOuter() {
        return thatOuterField; // outerField not defined
      }
    }
  }


}

let outer = new OuterClass();
let inner = new outer.InnerClass();
let win = inner.accessOuter();

alert(win); // test works!

不需要任何复杂的东西。

这个对我来说效果不是很好:

function use<T>(value: T) {return new class {with<U>(f: (value: T) => U) {return f(value)}}}

class OuterClass {
    private outerField = 1337;

    InnerClass = use(this).with(outerThis => class { 
        accessOuter() {
            return outerThis.outerField; // outerField not defined
        }
    }
}
const outer = new OuterClass()
const inner = new outer.InnerClass()
const win = inner.accessOuter()
console.log(win)