Güncellenmiş bir cevap: Kesişim türlerinin eklenmesinden bu yana, &
iki çıkarsanan türü anında "birleştirmek" mümkündür.
İşte bazı nesnelerin özelliklerini okuyan from
ve bunları bir nesnenin üzerine kopyalayan genel bir yardımcı onto
. Aynı nesneyi döndürür, onto
ancak her iki özellik kümesini de içeren yeni bir türle döndürür , bu nedenle çalışma zamanı davranışını doğru bir şekilde açıklar:
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 düzeyli yardımcı, hala bir tür iddiası gerçekleştirir, ancak tasarım gereği tür açısından güvenlidir. Bu yardımcı yerinde olduğunda, OP'nin problemini tam tip emniyetle çözmek için kullanabileceğimiz bir operatörümüz var:
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 Playground'da denemek için burayı tıklayın . Tipik olmak için kısıtladığımıza foo
dikkat edin Foo
, bu nedenle sonucunun merge
eksiksiz olması gerekir Foo
. Yani adlandırmak eğer bar
üzere bad
o zaman bir tür hatası alıyorum.
NB Bununla birlikte, burada hala bir tip delik var. TypeScript, bir tür parametresini "işlev değil" olarak sınırlandırmanın bir yolunu sağlamaz. Böylece kafanız karışabilir ve ikinci argüman olarak işlevinizi iletebilirsiniz merge
ve bu işe yaramaz. Dolayısıyla, bu ilan edilebilene kadar, onu çalışma zamanında yakalamalıyı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;
}
var f: { (): any; someValue: number; } = <{ (): any; someValue: number; }>{ ...(() => "Hello"), someValue: 3 };
.