Potete creare classi nidificate in TypeScript?


Risposte:


132

A partire da TypeScript 1.6 abbiamo espressioni di classe ( riferimento ).

Ciò significa che puoi fare quanto segue:

class Foo {
    static Bar = class {

    }
}

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

1
questo esempio non funziona in Typescript 1.6.3: Errore TS4028 La proprietà statica pubblica "Bar" della classe esportata ha o utilizza il nome privato "(Classe anonima)".
Sergey

1
@Sergey Ho avuto lo stesso problema, quindi ho iniziato a utilizzare gli spazi dei nomi secondo la mia risposta di seguito.
Dan Def

C'è un modo per creare un'interfaccia all'interno di una classe? cioè se vogliamo che Bar sia un'interfaccia
RoG

@LittaHervi - Un caso d'uso sarebbe la restituzione di un'implementazione privata di un'interfaccia esterna da, ad esempio, un metodo factory. Un altro esempio di Java (e altri) sono gli iteratori che richiedono un accesso privilegiato alle variabili membro della loro classe contenitore e tramite le regole di scoping lo fanno automaticamente, ma non si desidera mai che vengano esportati e istanziati direttamente.
Dave

35

Ecco un caso d'uso più complesso che utilizza espressioni di classe .

Consente alla classe interna di accedere ai privatemembri della classe esterna.

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à di accedere a membri privati ​​all'interno di un'espressione di classe "interna" è un bug?
bnieland

5
Ho verificato che questo sia un utilizzo corretto con il team TypeScript. github.com/Microsoft/TypeScript/issues/…
bnieland

1
è possibile che acceda al contesto genitore senza passare direttamente questo?
shabunc

@shabunc non a mia conoscenza
bnieland

19

Non sono riuscito a farlo funzionare con le classi esportate senza ricevere un errore di compilazione, invece ho usato gli spazi dei nomi :

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}

Stesso. "Foo" si riferisce solo a un tipo, ma qui viene utilizzato come spazio dei nomi.
Will Beason

12

Se ti trovi nel contesto di un file di dichiarazione del tipo, puoi farlo mescolando classi e spazi dei nomi:

// 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();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.