Können Sie verschachtelte Klassen in TypeScript erstellen?

Antworten:

130

Ab TypeScript 1.6 haben wir Klassenausdrücke ( Referenz ).

Dies bedeutet, dass Sie Folgendes tun können:

class Foo {
    static Bar = class {

    }
}

// works!
var foo = new Foo();
var bar = new Foo.Bar();
Basarat
quelle
1
Dieses Beispiel funktioniert nicht in Typescript 1.6.3: Fehler TS4028 Öffentliche statische Eigenschaft 'Bar' der exportierten Klasse hat oder verwendet den privaten Namen '(anonyme Klasse)'.
Sergey
1
@Sergey Ich hatte das gleiche Problem und begann, Namespaces gemäß meiner Antwort unten zu verwenden.
Dan Def
Gibt es eine Möglichkeit, eine Schnittstelle innerhalb einer Klasse zu erstellen? dh wenn wir wollen, dass Bar eine Schnittstelle sein wird
RoG
@LittaHervi - Ein Anwendungsfall wäre die Rückgabe einer privaten Implementierung einer externen Schnittstelle, beispielsweise von einer Factory-Methode. Ein weiteres Beispiel aus Java (und anderen) sind Iteratoren, die einen privilegierten Zugriff auf Mitgliedsvariablen ihrer enthaltenden Klasse benötigen, und dies durch Scoping-Regeln automatisch, aber Sie möchten niemals, dass diese direkt exportiert und instanziiert werden.
Dave
30

Hier ist ein komplexerer Anwendungsfall mit Klassenausdrücken .

Es ermöglicht der inneren Klasse , auf die privateMitglieder der äußeren Klasse zuzugreifen .

class classX { 
    private y: number = 0; 

    public getY(): number { return this.y; }

    public utilities = new class {
        constructor(public superThis: classX) {
        }
        public testSetOuterPrivate(target: number) {
            this.superThis.y = target;
        }
    }(this);    
}

const x1: classX = new classX();
alert(x1.getY());

x1.utilities.testSetOuterPrivate(4);
alert(x1.getY());

Codepen

bnieland
quelle
3
@RyanCavanaugh Ist die Möglichkeit, auf private Mitglieder innerhalb eines "inneren" Klassenausdrucks zuzugreifen, ein Fehler?
Bnieland
5
Ich habe überprüft, ob dies die korrekte Verwendung mit dem TypeScript-Team ist. github.com/Microsoft/TypeScript/issues/…
bnieland
1
Ist es möglich, auf den übergeordneten Kontext zuzugreifen, ohne diesen direkt zu übergeben?
Shabunc
@ Shabunc meines Wissens nicht
Bnieland
1
Genau das, wonach ich gesucht habe, danke!
Philippe
19

Ich konnte dies nicht mit exportierten Klassen zum Laufen bringen, ohne einen Kompilierungsfehler zu erhalten. Stattdessen habe ich Namespaces verwendet :

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}
Dan Def
quelle
Gleich. 'Foo' bezieht sich nur auf einen Typ, wird hier jedoch als Namespace verwendet.
Will Beason
12

Wenn Sie sich im Kontext einer Typdeklarationsdatei befinden, können Sie dazu Klassen und Namespaces mischen:

// foo.d.ts
declare class Foo {
  constructor();
  fooMethod(): any;
}

declare namespace Foo {
  class Bar {
    constructor();
    barMethod(): any;
  }
}

// ...elsewhere
const foo = new Foo();
const bar = new Foo.Bar();
danvk
quelle