Czy możesz tworzyć zagnieżdżone klasy w języku TypeScript?


Odpowiedzi:


131

Począwszy od TypeScript 1.6 mamy wyrażenia klasowe ( informacje ).

Oznacza to, że możesz wykonać następujące czynności:

class Foo {
    static Bar = class {

    }
}

// works!
var foo = new Foo();
var bar = new Foo.Bar();

1
ten przykład nie działa w Typescript 1.6.3: Błąd TS4028 Publiczna właściwość statyczna „Bar” wyeksportowanej klasy ma lub używa nazwy prywatnej „(klasa anonimowa)”.
Sergey

1
@Sergey Miałem ten sam problem, więc zacząłem używać przestrzeni nazw zgodnie z moją odpowiedzią poniżej.
Dan Def,

Czy istnieje sposób na stworzenie interfejsu wewnątrz klasy? tzn. jeśli chcemy, aby ten Bar był interfejsem
RoG

@LittaHervi - Jednym z przypadków użycia byłoby zwrócenie prywatnej implementacji interfejsu zewnętrznego z, na przykład, metody fabrycznej. Innym przykładem z języka Java (i innych) są iteratory, które wymagają uprzywilejowanego dostępu do zmiennych składowych ich klasy zawierającej, a reguły określania zakresu robią to automatycznie, ale nigdy nie chcesz, aby były one eksportowane i tworzone bezpośrednio.
Dave

30

Oto bardziej złożony przypadek użycia z użyciem wyrażeń klas .

Pozwala klasie wewnętrznej na dostęp do privateczłonków klasy zewnętrznej.

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 Czy możliwość dostępu do prywatnych członków wewnątrz „wewnętrznego” wyrażenia klasy jest błędem?
bnieland,

5
Sprawdziłem, że jest to poprawne użycie z zespołem TypeScript. github.com/Microsoft/TypeScript/issues/…
bnieland

1
czy możliwe jest uzyskanie dostępu do kontekstu nadrzędnego bez przekazywania tego bezpośrednio?
shabunc

@shabunc nie do mojej wiedzy
bnieland

1
Dokładnie to, czego szukałem, dziękuję!
Philippe

19

Nie mogłem tego zmusić do pracy z wyeksportowanymi klasami bez otrzymania błędu kompilacji, zamiast tego użyłem przestrzeni nazw :

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}

Podobnie. „Foo” odnosi się tylko do typu, ale jest tutaj używane jako przestrzeń nazw.
Will Beason,

12

Jeśli jesteś w kontekście pliku deklaracji typu, możesz to zrobić, mieszając klasy i przestrzenie nazw:

// 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();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.