En oppdatert svar: siden tillegg av krysningstyper via &, er det mulig å "slå sammen" to antatte typer på sparket.
Her er en generell medhjelper som leser egenskapene til et objekt fromog kopierer dem over et objekt onto. Den returnerer samme objekt onto, men med en ny type som omfatter begge settene med egenskaper, så korrekt beskriver runtime oppførsel:
function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
Object.keys(from).forEach(key => onto[key] = from[key]);
return onto as T1 & T2;
}
Dette lavt nivå helper har fortsatt utføre en type-påstand, men det er type trygt ved design. Med dette hjelper på plass, har vi en operatør som vi kan bruke til å løse OP problem med full typen sikkerhet:
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}`)
}
}
);
Klikk her for å prøve det ut i Loggfila barn . Merk at vi har begrenset footil å være av type Foo, så resultatet av mergemå være en komplett Foo. Så hvis du endrer navn bartil badså du får en type feil.
NB Det er fortsatt en type hull her, men. Maskinskrevet manuskript gir ikke en måte å begrense en type som parameter for å være "ikke er en funksjon". Så du kan bli forvirret og passere din funksjon som andre argument til merge, og det ville ikke fungere. Så inntil dette kan bli erklært, må vi ta det under kjøring:
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;
}