Você pode criar classes aninhadas no TypeScript?


Respostas:


132

A partir do TypeScript 1.6, temos expressões de classe ( referência ).

Isso significa que você pode fazer o seguinte:

class Foo {
    static Bar = class {

    }
}

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

1
este exemplo não funciona no texto de tipo 1.6.3: Erro TS4028 A propriedade estática pública 'Bar' da classe exportada tem ou está usando o nome privado '(classe anônima)'.
Sergey

1
@Sergey Eu tive o mesmo problema, então comecei a usar namespaces de acordo com minha resposta abaixo.
Dan Def

Existe uma maneira de criar interface dentro de uma classe? ou seja, se quisermos que a barra seja uma interface
RoG

@LittaHervi - Um caso de uso seria retornar uma implementação privada de uma interface externa de, por exemplo, um método de fábrica. Outro exemplo de Java (e outros) são os iteradores que requerem acesso privilegiado a variáveis ​​de membro de sua classe contida e, por meio de regras de escopo, fazem isso automaticamente, mas você nunca deseja que eles sejam exportados e instanciados diretamente.
Dave

35

Aqui está um caso de uso mais complexo usando expressões de classe .

Ele permite que a classe interna acesse os privatemembros da classe externa.

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 A capacidade de acessar membros privados dentro de uma expressão de classe "interna" é um bug?
bnieland

5
Eu verifiquei que este é o uso correto com a equipe TypeScript. github.com/Microsoft/TypeScript/issues/…
bnieland

1
é possível acessar o contexto pai sem passar isso diretamente?
shabunc de

@shabunc, não que eu saiba
bnieland

19

Não consegui fazer isso funcionar com classes exportadas sem receber um erro de compilação; em vez disso, usei namespaces :

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}

Mesmo. 'Foo' refere-se apenas a um tipo, mas está sendo usado como um namespace aqui.
Will Beason de

12

Se você estiver no contexto de um arquivo de declaração de tipo, poderá fazer isso misturando classes e namespaces:

// 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();
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.