更新的答案:由于通过添加了交叉路口类型&
,因此可以即时“合并”两个推断的类型。
这是一个通用帮助程序,它读取某些对象的属性from
并将其复制到对象上onto
。它返回相同的对象,onto
但具有包含两组属性的新类型,因此可以正确描述运行时行为:
function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
Object.keys(from).forEach(key => onto[key] = from[key]);
return onto as T1 & T2;
}
该低级帮助程序仍会执行类型声明,但是从设计上讲它是类型安全的。有了此辅助程序,我们就可以使用操作员来解决OP的全类型安全问题:
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中尝试一下。请注意,我们已限制foo
为类型Foo
,因此结果merge
必须是完整的Foo
。因此,如果您重命名bar
为bad
则会出现类型错误。
注意:这里仍然有一个类型的孔。TypeScript没有提供将类型参数约束为“不是函数”的方法。因此,您可能会感到困惑,并将函数作为第二个参数传递给merge
,这将不起作用。因此,在可以声明之前,我们必须在运行时捕获它:
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 };
。