Pouvez-vous créer des classes imbriquées dans TypeScript?


Réponses:


131

À partir de TypeScript 1.6, nous avons des expressions de classe ( référence ).

Cela signifie que vous pouvez effectuer les opérations suivantes:

class Foo {
    static Bar = class {

    }
}

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

1
cet exemple ne fonctionne pas dans Typescript 1.6.3: Erreur TS4028 Propriété statique publique 'Bar' de la classe exportée a ou utilise le nom privé '(classe anonyme)'.
Sergey

1
@Sergey J'ai eu le même problème, alors j'ai commencé à utiliser les espaces de noms selon ma réponse ci-dessous.
Dan Def le

Existe-t-il un moyen de créer une interface à l'intérieur d'une classe? c'est-à-dire si nous voulons que Bar soit une interface
RoG

@LittaHervi - Un cas d'utilisation serait de retourner une implémentation privée d'une interface externe à partir, par exemple, d'une méthode de fabrique. Un autre exemple de Java (et d'autres) sont les itérateurs qui nécessitent un accès privilégié aux variables membres de leur classe contenante et via des règles de portée le font automatiquement, mais vous ne voulez jamais que ces derniers soient exportés et instanciés directement.
Dave

30

Voici un cas d'utilisation plus complexe utilisant des expressions de classe .

Il permet à la classe interne d'accéder aux privatemembres de la classe externe.

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 La possibilité d'accéder à des membres privés dans une expression de classe "interne" est-elle un bogue?
bnieland

5
J'ai vérifié qu'il s'agissait d'une utilisation correcte avec l'équipe TypeScript. github.com/Microsoft/TypeScript/issues/…
bnieland

1
est-il possible d'accéder au contexte parent sans le passer directement?
shabunc

@shabunc pas à ma connaissance
bnieland

1
Exactement ce que je cherchais, merci!
Philippe le

19

Je ne pouvais pas faire fonctionner cela avec les classes exportées sans recevoir une erreur de compilation, à la place j'ai utilisé des espaces de noms :

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}

Même. «Foo» ne fait référence qu'à un type, mais est utilisé ici comme espace de noms.
Will Beason

12

Si vous êtes dans le contexte d'un fichier de déclaration de type, vous pouvez le faire en mélangeant des classes et des espaces de noms:

// 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();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.