Можете ли вы создавать вложенные классы в TypeScript?

Ответы:

131

Начиная с TypeScript 1.6 у нас есть выражения классов ( ссылка ).

Это означает, что вы можете делать следующее:

class Foo {
    static Bar = class {

    }
}

// works!
var foo = new Foo();
var bar = new Foo.Bar();
басарат
источник
1
этот пример не работает в Typescript 1.6.3: Ошибка TS4028 Открытое статическое свойство «Панель» экспортированного класса имеет или использует частное имя «(Анонимный класс)».
Сергей
1
@Sergey У меня была такая же проблема, поэтому я начал использовать пространства имен в соответствии с моим ответом ниже.
Дэн Деф
Есть ли способ создать интерфейс внутри класса? то есть, если мы хотим, чтобы этот Бар был интерфейсом
RoG
@LittaHervi - одним из вариантов использования может быть возврат частной реализации внешнего интерфейса, например, из фабричного метода. Другим примером из Java (и других) являются итераторы, которым требуется привилегированный доступ к переменным-членам их содержащего класса и через правила области действия автоматически делают это, но вы никогда не хотите, чтобы они экспортировались и создавались напрямую.
Дэйв
30

Вот более сложный вариант использования с использованием выражений классов .

Это позволяет внутреннему классу получать доступ к privateчленам внешнего класса.

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

кодовый ключ

Bnieland
источник
3
@RyanCavanaugh Является ли возможность доступа к закрытым членам внутри выражения "внутреннего" класса ошибкой?
bnieland
5
Я подтвердил, что это правильное использование с командой TypeScript. github.com/Microsoft/TypeScript/issues/…
bnieland 01
1
возможно ли получить доступ к родительскому контексту, не передавая это напрямую?
shabunc
@shabunc, насколько мне известно,
bnieland
1
Именно то, что я искал, спасибо!
Филипп,
19

Я не мог заставить это работать с экспортированными классами без получения ошибки компиляции, вместо этого я использовал пространства имен :

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}
Дэн Деф
источник
Тем же. «Foo» относится только к типу, но здесь используется как пространство имен.
Уилл Бисон
12

Если вы находитесь в контексте файла объявления типа, вы можете сделать это, смешав классы и пространства имен:

// 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();
данвк
источник