Daktilo özelliklere sahip bir işlev nesnesini oluşturmak

oy
46

Ben de bunun üzerine tutulan bazı özelliklere sahip bir işlev nesnesini oluşturmak istiyorum. JavaScript Mesela ben yapardım:

var f = function() { }
f.someValue = 3;

Şimdi daktilo ben bu tipini tarif edebilir:

var f: { (): any; someValue: number; };

Ancak aslında bir döküm gerektirmeden, bunu inşa edemeyiz. Gibi:

var f: { (): any; someValue: number; } =
    <{ (): any; someValue: number; }>(
        function() { }
    );
f.someValue = 3;

Nasıl bir döküm olmadan bu kuracağına?

Oluştur 07/10/2012 saat 07:08
kaynak kullanıcı
Diğer dillerde...                            


9 cevaplar

oy
73

Güncelleme: Bu cevap typescript önceki sürümlerinde en iyi çözüm oldu ama yeni sürümlerinde (diğer cevaplar bakın) mevcuttur daha iyi seçenek vardır.

Kabul cevap çalışır ve bazı durumlarda gerekli olabilir, fakat nesneyi oluşturulmasına yönelik hiçbir tür güvenliği sağlama dezavantajı var. Eğer tanımlanmamış bir özellik eklemeyi denerseniz Bu teknik, en az bir tip hata verir.

interface F { (): any; someValue: number; }

var f = <F>function () { }
f.someValue = 3

// type error
f.notDeclard = 3
Cevap 05/09/2013 saat 16:12
kaynak kullanıcı

oy
34

Typescript aracılığıyla bu durumda işlemek için tasarlanmıştır beyan birleştiği :

Ayrıca, bir işlev oluşturarak ve ardından fonksiyon üzerine eklenmesiyle elde edilen başka işlevleri uzanan JavaScript uygulama aşina olabilir. Typescript tip-güvenli bir şekilde böyle tanımları oluşturmak için deklarasyon birleştirilmesi kullanır.

Beyan birleştirme bize bir şey bir işlev ve ad (iç modül) hem olduğunu söylemek sağlar:

function f() { }
namespace f {
    export var someValue = 3;
}

Bu yazarak korur ve bize hem yazmanıza olanak tanır f()ve f.someValue. Bir yazarken .d.tsJavaScript kodu mevcut dosyayı kullanın declare:

declare function f(): void;
declare namespace f {
    export var someValue: number;
}

işlevlerine özelliklerini ekleme yüzden bunu önlemek için çalışıyorum, ama kullanan veya daha eski JS kodu dönüştürürken gerekli olabilir, genellikle daktilo kafa karıştırıcı ya da beklenmedik kalıptır. Bu dış ile iç modülleri (ad) karıştırmak için uygun olacaktır tek kez biridir.

Cevap 28/10/2015 saat 13:47
kaynak kullanıcı

oy
27

Bu (daktilo 2.x) şimdi kolaylıkla elde edilebilir Object.assign(target, source)

örnek:

Burada görüntü açıklama girin

Burada sihirli yani Object.assign<T, U>(...)bir dönüş yazılan kavşak tipini T & U.

Bu bilinen bir arabirime gideren Bağlayıcılığı da düz ileri:

interface Foo {
  (a: number, b: string): string[];
  foo: string;
}

let method: Foo = Object.assign(
  (a: number, b: string) => { return a * a; },
  { foo: 10 }
); 

Hata: ece: fan olarak değerlendirilmez sayısı: dize
hatası: dize [] (dönüş tip) atanabilir değil sayı

uyarı: Eğer gerekebilir polyfill eski tarayıcıları hedef alan ise Object.assign.

Cevap 25/01/2017 saat 13:43
kaynak kullanıcı

oy
17

gereklilik sadece inşa etmek ve bir döküm olmadan bu işlevi için "f" atamak Yani, eğer burada olası bir çözümdür:

var f: { (): any; someValue: number; };

f = (() => {
    var _f : any = function () { };
    _f.someValue = 3;
    return _f;
})();

Esasen, bu atama yapılmadan önce o imzayı maç olacak bir nesne "inşa" için değişmez bir öz yürütme işlevini kullanır. Sadece tuhaflık aksi derleyici henüz nesne üzerinde var olmayan bir mülke atıyorsanız o ağlıyor, fonksiyonun iç beyanı türü 'herhangi' olması gerekiyor.

DÜZENLEME: kodu biraz basitleştirilmiş.

Cevap 07/10/2012 saat 17:33
kaynak kullanıcı

oy
1

Ben çok basit ama kesinlikle mümkün olduğunu söyleyemeyiz:

interface Optional {
  <T>(value?: T): OptionalMonad<T>;
  empty(): OptionalMonad<any>;
}

const Optional = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.empty = () => OptionalCreator();

Meraklı var ise bu typescript / JavaScript sürümü ile benim bir özünden olduğuOptional

Cevap 07/02/2018 saat 23:57
kaynak kullanıcı

oy
1

Güncellenmiş cevap: aracılığı kavşak tiplerinin yanı sıra bu yana &, bu anında iki çıkarsama yoluyla türleri "birleştirme" mümkündür.

İşte bazı nesnenin özelliklerini okuyan bir genel yardımcı olduğunu frombir nesnenin üzerine ve kopya onları onto. Aynı nesnesi geri ontodoğru olarak çalışma zamanı davranışını tanımlayan, özelliklerin iki seti içeren yeni bir türü ile ancak:

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}

Bu düşük seviyeli yardımcı hala tip iddiayı performans gösteriyor, ama bu tip-güvenli tasarım gereğidir. yerine bu yardımcı ile, biz tam tip güvenliği ile OP'ın sorunu çözmek için kullanabileceğiniz bir operatöre sahiptir:

interface Foo {
    (message: string): void;
    bar(count: number): void;
}

const foo: Foo = merge(
    (message: string) => console.log(`message is ${message}`), {
        bar(count: number) {
            console.log(`bar was passed ${count}`)
        }
    }
);

Typescript Oyun alanı denemek için burayı tıklayın . Biz kısıtlı olduğunu unutmayın footürden olmalı Foo, böylece sonucu mergetam olması gerekir Foo. Yani adlandırmak eğer barüzere bado zaman bir tür hatası alıyorum.

NB ancak yine de burada bir tür delik vardır. Typescript "değil bir işlev" olarak bir tür parametresi sınırlamak için bir yol sağlamaz. Yani karışık ve ikinci argüman olarak işlev geçebileceği mergeve bu işe yaramaz. Bu ilan edilene kadar Yani, biz zamanında yakalamak zorundayız:

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    if (typeof from !== "object" || from instanceof Array) {
        throw new Error("merge: 'from' must be an ordinary object");
    }
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}
Cevap 10/03/2016 saat 19:14
kaynak kullanıcı

oy
1

Kısayol olarak, dinamik [ 'mülkiyet'] erişimciyi kullanarak nesne değeri atayabilirsiniz:

var f = function() { }
f['someValue'] = 3;

Bu tür denetlemesi atlar. bilerek, tesisi aynı şekilde erişmek zorunda çünkü Ancak, oldukça güvenlidir:

var val = f.someValue; // This won't work
var val = f['someValue']; // Yeah, I meant to do that

Eğer gerçekten mülk değerini işaretleyerek türü isterseniz Ancak, bu işe yaramaz.

Cevap 11/10/2012 saat 05:38
kaynak kullanıcı

oy
0

Eğer düz JS olduğu gibi Eski bir soru, ama 3.1 ile başlayan typescript sürümleri için, sadece sürece bir işlevi bildirimi veya kullandıkça, mülkiyet atama yapabileceği constsizin değişken için anahtar kelime:

function f () {}
f.someValue = 3; // fine
const g = function () {};
g.someValue = 3; // also fine
var h = function () {};
h.someValue = 3; // Error: "Property 'someValue' does not exist on type '() => void'"

Referans ve çevrimiçi örnek .

Cevap 26/11/2018 saat 21:38
kaynak kullanıcı

oy
0

Bu güçlü yazarak yola, fakat yapabileceğin

var f: any = function() { }
f.someValue = 3;

Etrafında baskıcı güçlü yazarak almaya çalışırken eğer ben bu soruyu bulduğumda olduğu gibi. Ne yazık ki bu bir vaka typescript sen geri adım typescript söylemek var bu yüzden tamamen geçerli JavaScript üzerinde başarısız olduğunu.

"JavaScript tamamen geçerli typescript olan" false olarak değerlendirilir. (Not: 0.95 kullanılarak)

Cevap 21/02/2014 saat 16:59
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more