Un răspuns actualizat: întrucât adăugarea de tipuri de intersecție , prin intermediul &, este posibil să se „fuzioneze“ două tipuri deduse pe zbor.
Iată un ajutor general , care citește proprietățile unui obiect fromși să le copii de peste un obiect onto. Ea se întoarce același obiect , ontodar cu un nou tip , care include ambele seturi de proprietăți, care descrie în mod corect comportamentul de rulare:
function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
Object.keys(from).forEach(key => onto[key] = from[key]);
return onto as T1 & T2;
}
Acest ajutor de nivel scăzut încă nu efectuează o afirmație de tip, dar este de tip sigur prin design. Cu acest ajutor, în loc, avem un operator pe care o putem folosi pentru a rezolva problema PO cu siguranță de tip complet:
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}`)
}
}
);
Click aici pentru a încerca în typescript Playground . Rețineți că am constrânsă foosă fie de tip Foo, astfel încât rezultatul mergetrebuie să fie completă Foo. Deci , dacă redenumiți barsă badatunci veți obține o eroare de tip.
NB Există încă o gaură tip aici, cu toate acestea. Typescript nu oferă o modalitate de a constrânge un parametru de tip să fie „nu este o funcție“. Deci , ai putea obține confuz și să treacă funcția ta ca al doilea argument merge, și că nu ar funcționa. Deci , până când acest lucru poate fi declarată, trebuie să - l prindem în timpul rulării:
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;
}