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

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


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 { }
}

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();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.