2017-12-06 9 views
1

Ich habe diese Funktion applyObject, die ich gerne eingeben würde. Die Paramter für die Funktion sind von T und V wo V ein Objekt von Funktionen ist:Wie wird ein Objekt von Gettern auf ihren Wert abgebildet?

type V = { [key: string]: <R>(t: T) => R }; 

und T ist der Typ I über alle Funktionen von V einspeisen wollen, wenn angewendet. Gibt es eine Möglichkeit, dies zu tun?

Ich denke, dass es mit einem abgebildeten Typ möglich ist, aber ich bin unsicher. Ich denke so:

function applyObject<T, V extends { [key: string]: (t: T) => any }>(t: T, v: V) { 
    return Object.entries(v).reduce((applied, [_key, func]) => { 
    const key = _key as keyof V; 
    applied[key] = func(t); 
    return applied; 
    }, {} as {[P in keyof V]: Invoke<V[P]>}); // `Invoke` doesn't exist 
} 

const applied = applyObject(
    { one: 1, two: 'something' }, 
    { a: t => t.one, b: t => t.two } 
); 

applied.a; // should give intellisense as number 
applied.b // should give intellisense as string 
+0

Ich glaube nicht, dass es möglich ist, das Problem ist, dass selbst 'V' nicht gut typisiert ist, ich vermute, Sie möchten sagen, dass jede Funktion von' V' ein 'T' nimmt und jeden Typ zurückgeben kann , aber die Art, wie Sie es 'R' definieren, ist Sache des Anrufers und nicht der Funktion. –

+0

@ TitianCernicova-Dragomir Ich habe 'R' aus der Frage entfernt. Ich bin mir nicht sicher, ob es nötig ist. –

Antwort

2

Wie wäre es damit:

type V<T, A> = {[K in keyof A]: (t: T) => A[K]}; 
function applyObject<T, A extends any>(t: T, v: V<T, A>): A { 
    const ret = {} as A; 
    for (const k in v) { 
    ret[k] = v[k](t); 
    } 
    return ret; 
} 

const applied = applyObject(
    { one: 1, two: 'something' }, 
    { a: t => t.one, b: t => t.two } 
); // inferred as {a: number, b: string} 

Die Idee ist es, die V Art in Bezug auf die Eingangsobjekttyp T und die Art A der beabsichtigten Rückkehr zum Ausdruck bringen Wert von applyObject(). Die Schlüssel von V<T,A> sind die gleichen wie die von A, und die Werte sind Funktionen von T zu dem entsprechenden Eigenschaftstyp A. Mit dieser Definition können Sie inference from mapped types eingeben, um applyObject() einzugeben.

(Es gibt einen kleinen Nachteil hier Wenn Sie sehen, ich in applyObject() die A Parameter definiert A extends any zu sein, das sollte nicht nötig sein;... Jede Art any in Typoskript erstreckt Aber ohne sie wird A als {a: any, b: any} gefolgert die ist nicht besonders nützlich.Ich habe keine Ahnung, warum A extends any behebt es, aber es tut.Jemand besser vertraut mit der Nitty Gritty von TypScript-Typ Inferenz haben irgendwelche Ideen?)

Ich modifizierte auch die Umsetzung, da es für mich einfacher war um TypeScript davon zu überzeugen, dass es typsicher war. Fühlen Sie sich frei, Ihre eigene Implementierung zu verwenden, wenn Sie TypeScript glücklich machen oder in die Stille zwingen können.

Wie auch immer die Hoffnung, das hilft. Viel Glück!

+0

Sie sind ein Assistent –

+0

und ich denke, Typoskript-Typen die Rückkehr von 'Array.prototype.reduce' als der erste Akkumulator so' .Reduce (/*...*/, {} wie A) 'könnte gearbeitet haben –

Verwandte Themen