2012-10-18 21 views
9

kontrol yazmayın ve çek yazmak için başarısız aşağıdaki zaman biraz karışık oldu:Arayüzler ben daktilo yapı imzalarla arayüzlerle biraz çalıyorum

class Foo { 
    constructor() { 
    } 
} 

interface Bar { 
    new(): Bar; 
} 

function Baz(C : Bar) { 
    return new C() 
} 

var o = Baz(Foo); 

türü hatası olduğunu :

Sağlanan parametreleri çağrı hedefinin herhangi imza eşleşmiyor: Türü 'Bar' bir yapı imzasını gerektirir, ancak Tip: türleri 'yeni() => Foo' ve 'Bar' olan uyumsuz imzaları Construct 'Foo' eksikliği s bir (C: Bar) => Bar

Foo'nun yapıcısının türü() => Foo'dur ve Bar'ın söylediği şey budur. Burada bir şey mi eksik?

cevap

1

Sorun (en azından TypeScript derleyicinin bakış açısından), Bar ürününün new yönteminin imzasıdır. Eğer aşağıdaki ile Bar tanımını, çalışıyor

interface Bar { 
    new(): any; 
} 

değiştirin. Dönüş değeri çalışmadığı için new(): Foo, sadece Bar kullanabilirsiniz.

5

İşte kodunuzun ince bir değişiklikle güncellenmiş bir sürümü.

Bar arabirimini, var olmasını umduğumuz işlevler ve değişkenler ile tanımlarız.

Sonraki, arabirimiyle Bar arabirimini genişletiyoruz. Bu sadece bir Bar döndüren bir kurucu tanımladı. FooBar uygulayan ve bir kurucuya sahip ve Baz bir NewableBar gerektirdiğinden

, her şey kontrol edilir.

Bu, any'dan biraz daha ayrıntılıdır, ancak istediğiniz denetimi verir.

interface Bar { 

} 

interface NewableBar extends Bar { 
    new(); 
} 

class Foo implements Bar { 
    constructor() { 

    } 
} 

function Baz(C : NewableBar) { 
    return new C() 
} 

var o = Baz(Foo); 
+0

'Herhangi birini kullanmak yerine süper bir arabirim kullanırsınız ("implements" ve "extends", btw). Tamam, sanırım, ve herşeyden daha iyi, ama bir şey hala beni rahatsız ediyor: Neden NewableBar :: new() '' NewableBar'ı döndürmeye izin veremiyorsun? Neden "NewableBar" dan daha genel bir ** (ve tabii ki en azından Foo gibi jenerik) olan bir tür olmak zorundadır? –

+0

@AdrianLang Açık olması için açık miras ve uygulamalara koydum, ama siz haklısınız - TypeScript, her şey eşleşirse bunları mutlu bir şekilde çıkaracaktır. Belirli bir türdeki bir yönteme ilişkin 'new()' imzasını işlemeye çalışırken bir yorumlama sorunu vardır. – Fenton

+0

Ancak, Foo'ya herhangi bir şey eklemeye çalıştığınızda bu kırılır. Düzenleme: Üzgünüm, yanlış yapıyordum. Yapım imzam şöyle olmalıdır: 'new (... _: any []): Bar;' – farre

1

Sanırım bunu nereden alıyorsunuz ve sanırım farklı bir yaklaşıma ihtiyacınız var.

Bu örnek şöyle demektedir:

  • Baz zorunluluk newable bir öğe geçirilecek.
  • Baz bir Bar
  • newable olmak Tüm Bar'ın ihtiyacı dönecektir, sadece bu Baz
  • İşte

geçirilen örnektir:

interface Bar { 
    sayHello(name: string): void; 
} 

interface Newable { 
    new(); 
} 

class Foo implements Bar { 
    constructor() { 

    } 

    sayHello(name: string) { 
     window.alert('Hello ' + name); 
    } 
} 

function Baz(C : Newable) { 
    return <Bar> new C() 
} 

var o = Baz(Foo); 
o.sayHello('Bob'); 

bunun Tek tehlike Yaklaşım, Baz fonksiyonuna Bar olmayan yeni bir şeyleri geçebilmenizdir.Bir argümandan bir nesne yaratarak dinamik bir özellik kullandığınız için, önceden başlatılmış bir nesneyi geçmek istemediğiniz sürece bu kaçınılmazdır. Bu durumda, Baz bir mutluluktan ziyade bir Bar'ı kabul etmekten mutluluk duyar.

+0

Evet, bu hatlardaki bir şey başarmak istediğim şeydi. İstisna ile 'Bar' ve 'Newable' için tek bir arayüz olmasını istedim. Teşekkürler. – farre

1

Bunun eski bir soru olduğunu biliyorum, ancak bugün benzer bir şeye ihtiyacım vardı ve postayla karşılaştım.

interface Bar { 
    sayHello(name: string); 
} 

class Foo implements Bar { 
    sayHello(name: string) { 
     window.alert("Hello " + name); 
    } 
} 

function Baz(c: new() => Bar) { 
    return new C(); 
} 

var o = Baz(Foo); 
o.sayHello("Bob"); 

Temelde arabirimler sadece bu yüzden olacak fonksiyonuna yapılmalıdır varlığını belli yapıcı gerektiren bir nesnenin örneğine sözleşmesini tanımlayabiliriz: Bazı deneme yanılma sonra aşağıdaki çözüm geldi kurucu çağırıyor. Bu yöntem aynı zamanda jenerik güzel bir şekilde oynar:

function Baz<T extends Bar>(c: new() => T) { 
    return new c(); 
} 

var o = Baz(Foo); 

değişken Yukarıdaki örnekte türü Fan gibi çıkarılabilir olan "O".

İlgili konular