Építs egy függvény objektum tulajdonságokkal géppel

szavazat
46

Szeretnék létrehozni egy függvény objektum, amely szintén bizonyos tulajdonságait tartotta rajta. Például a JavaScript tennék:

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

Most géppel tudom leírni, hogy milyen típusú ez, mint:

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

Azonban nem tudok ténylegesen építeni, anélkül, hogy a leadott. Mint például:

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

Hogyan tudja építeni ezt nélkül leadott?

A kérdést 07/10/2012 07:08
a forrás felhasználó
Más nyelveken...                            


9 válasz

szavazat
73

Frissítés: A válasz az volt, hogy a legjobb megoldás a korábbi verziókban géppel, de vannak jobb lehetőségek állnak rendelkezésre az újabb verziójú (lásd a többi válaszok).

Az elfogadott válasz működik, és szükség lehet bizonyos helyzetekben, de a hátránya a biztosító nem típusú biztonsági felépítéséhez az objektumot. Ez a technika legalább dobni egy típus hiba, ha megpróbálja felvenni egy definiálatlan tulajdon.

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

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

// type error
f.notDeclard = 3
Válaszolt 05/09/2013 16:12
a forrás felhasználó

szavazat
34

Gépelt kezelésére tervezték ebben az esetben a nyilatkozat összevonása :

Ön is ismerik a JavaScript gyakorlat kialakításának függvényében, majd kiterjesztése funkció további hozzáadásával tulajdonságai rá a funkciót. Gépelt használ nyilatkozatot összevonása felépíteni definíciók, mint ez a fajta biztonságos módja.

Nyilatkozat összevonása lehetővé teszi számunkra, hogy valami egyszerre funkció és a névtér (belső modul):

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

Ez megőrzi a gépelést, és lehetővé teszi számunkra, írja mindkét f()és f.someValue. Írásakor .d.tsfájl meglévő JavaScript kódot, declare:

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

Új ingatlanokat a funkciók gyakran zavaros vagy váratlan minta géppel, így próbálják meg elkerülni, de ez is lehet szükség, amikor vagy átalakítására, idősebb JS kódot. Ez az egyik az egyetlen alkalommal indokolt lenne összekeverni a belső modulok (névterek) külső.

Válaszolt 28/10/2015 13:47
a forrás felhasználó

szavazat
27

Ez könnyen megvalósítható most (géppel 2.x) az Object.assign(target, source)

példa:

írja kép leírása itt

A varázslat az, hogy Object.assign<T, U>(...)a beírt visszatérni a kereszteződés típusú T & U.

Érvényesítése, hogy ez megoldja az ismert felület is egyenesen előre:

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

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

Hiba: foo: szám nem besorolható ize: string
Hiba: szám nem besorolható string [] (visszatérési típus)

kikötés: akkor lehet, hogy Polyfill Object.assign ha célozzuk régebbi böngészők.

Válaszolt 25/01/2017 13:43
a forrás felhasználó

szavazat
17

Tehát, ha az a követelmény, hogy egyszerűen építeni, és hozzá ezt a funkciót az „f” nélkül öntött, itt van egy lehetséges megoldás:

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

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

Lényegében ez használ egy önvégrehajtás funkciót szó a „konstrukció” egy tárgy, amely egyezik, hogy az aláírás előtt a feladat kész. Az egyetlen furcsaság az, hogy a belső nyilatkozata funkciót kell lennie típusú „bármilyen”, különben a fordító sír, hogy te rendelünk a tulajdonság, amely nem létezik a tárgy még.

EDIT: Egyszerűsített a kód egy kicsit.

Válaszolt 07/10/2012 17:33
a forrás felhasználó

szavazat
1

Nem tudom megmondani, hogy ez nagyon egyszerű, de ez biztosan lehetséges:

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

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

ha megvan kíváncsi ez egy lényeget én a géppel / JavaScript változataOptional

Válaszolt 07/02/2018 23:57
a forrás felhasználó

szavazat
1

A frissített válasz: mivel hozzáadásával kereszteződés típusok keresztül &, lehetőség van a „merge” két kikövetkeztetett típusú menet közben.

Itt egy általános segítőt, hogy beolvassa a tulajdonságait valami tárgyat from, és átmásolja egy objektum fölé onto. Ugyanazokat az objektumot onto, hanem egy új típusú, amely magában foglalja mindkét tulajdonságait, így pontosan leírja a futási viselkedés:

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

Ez az alacsony szintű helper nem is végrehajthatja a típus-állítás, de ez típus-biztonságosnak design. Ezzel a segítő a helyén, van egy operátor, hogy tudjuk használni, hogy megoldja a problémát OP teljes típus biztonság:

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}`)
        }
    }
);

Kattintson ide, hogy próbálja ki a géppel Playground . Figyeljük meg, hogy akadályozza a footípusúnak Foo, így az eredmény mergekell, hogy legyen egy teljes Foo. Tehát, ha átnevezi bara badakkor kap egy típus hiba.

NB : Még van egy lyuk típusú van, de. Géppel nem nyújt olyan módon, hogy korlátozzák a típusú paraméter, hogy „nem egy funkció”. Így lehet összezavarodnak, és adja át a funkciója, mint a második argumentum merge, és hogy ez nem működik. Tehát, amíg ez lehet nyilvánítani, meg kell fogni, hogy a futás:

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;
}
Válaszolt 10/03/2016 19:14
a forrás felhasználó

szavazat
1

Mint egy parancsikont, akkor automatikusan rendeli a tárgy értékét a [ „tulajdon”] akcesszora:

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

Ez megkerüli a típus ellenőrzése. Azonban ez elég biztonságos, mert van, hogy szándékosan elérni a tulajdonság azonos módon:

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

Azonban, ha szeretné a típus ellenőrzése az ingatlan értékét, ez nem fog működni.

Válaszolt 11/10/2012 05:38
a forrás felhasználó

szavazat
0

Régi kérdés, de változatai géppel kezdve 3.1, akkor egyszerűen tegye a tulajdonság hozzárendelés, ahogy azt a sima JS, amíg használni a funkciót nyilatkozatot vagy a constkulcsszó az a változót:

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'"

Referencia és internetes példa .

Válaszolt 26/11/2018 21:38
a forrás felhasználó

szavazat
0

Ez eltér az erős gépelés, de meg tudod csinálni

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

ha megpróbálják megkerülni elnyomó erős gépelés, mint én, amikor találtam ezt a kérdést. Sajnos ez esetben géppel sikertelen tökéletesen érvényes JavaScript úgy van, hogy azt mondja géppel meghátrálni.

„Te JavaScript tökéletesen érvényes géppel” értéke hamis. (Megjegyzés: a 0,95)

Válaszolt 21/02/2014 16:59
a forrás felhasználó

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