Чи можете ви створити вкладені класи в 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 Відкрите статичне властивість 'Bar' експортованого класу має або використовує приватне ім'я '(Anonymous class)'.
Сергій

1
@Sergey У мене була та сама проблема, тому я почав використовувати простори імен відповідно до моєї відповіді нижче.
Dan Def

Чи є спосіб створити інтерфейс всередині класу? тобто якщо ми хочемо, щоб Bar був інтерфейсом
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());

codepen


3
@RyanCavanaugh Чи є можливістю доступу до приватних членів усередині виразу "внутрішнього" класу помилка?
bnieland

5
Я переконався, що це правильне використання з командою TypeScript. github.com/Microsoft/TypeScript/issues/…
bnieland

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();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.