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();

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


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

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();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.