Bisakah Anda membuat kelas bersarang di TypeScript?

Jawaban:

132

Dimulai dengan TypeScript 1.6 kita memiliki ekspresi kelas ( referensi ).

Artinya, Anda dapat melakukan hal berikut:

class Foo {
    static Bar = class {

    }
}

// works!
var foo = new Foo();
var bar = new Foo.Bar();
basarat
sumber
1
contoh ini tidak berfungsi di Skrip Ketik 1.6.3: Kesalahan TS4028 Properti statis publik 'Bar' dari kelas yang diekspor memiliki atau menggunakan nama pribadi '(kelas Anonim)'.
Sergey
1
@Sergey Saya memiliki masalah yang sama jadi mulai menggunakan ruang nama sesuai jawaban saya di bawah ini.
Dan Def
Apakah ada cara untuk membuat antarmuka di dalam kelas? yaitu jika kita ingin Bar itu akan menjadi antarmuka
RoG
@LittaHervi - Salah satu kasus penggunaan adalah mengembalikan implementasi pribadi antarmuka eksternal dari, misalnya, metode pabrik. Contoh lain dari Java (dan lainnya) adalah iterator yang memerlukan akses istimewa ke variabel anggota dari kelas yang memuatnya dan melalui aturan pelingkupan secara otomatis melakukannya, tetapi Anda tidak ingin ini diekspor dan dibuat secara langsung.
Dave
35

Berikut adalah kasus penggunaan yang lebih kompleks menggunakan ekspresi kelas .

Ini memungkinkan kelas dalam untuk mengakses privateanggota kelas luar.

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

bnieland
sumber
3
@RyanCavanaugh Apakah kemampuan untuk mengakses anggota pribadi di dalam ekspresi kelas "batin" merupakan bug?
bnieland
5
Saya memverifikasi bahwa ini adalah penggunaan yang benar dengan tim TypeScript. github.com/Microsoft/TypeScript/issues/…
bnieland
1
apakah mungkin itu mengakses konteks induk tanpa meneruskan ini secara langsung?
shabunc
@shabunc tidak sepengetahuan saya
bnieland
19

Saya tidak bisa mendapatkan ini untuk bekerja dengan kelas yang diekspor tanpa menerima kesalahan kompilasi, sebagai gantinya saya menggunakan ruang nama :

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}
Dan Def
sumber
Sama. 'Foo' hanya mengacu pada suatu tipe, tetapi digunakan sebagai namespace di sini.
Akan Beason
12

Jika Anda berada dalam konteks file deklarasi tipe, Anda dapat melakukan ini dengan mencampur kelas dan namespace:

// 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();
danvk
sumber