以下接口定义了一个函数,该函数接受一个回调函数并返回该回调返回的值。
export interface MonitoredOperation {
<T = any>(operationName: string, operation: () => T | Promise<T>): T | Promise<T>;
}
问题是,如果我在回调将始终返回一种类型的上下文中使用此函数,TypeScript仍然认为外部函数可以返回任一类型。
例如,如果我编写以下代码,
public addNumbersAsync(n1: number, n2: number, n3: number, n4: number): Promise<number> {
return this.monitoredOperation("addNumbers", () => Promise.resolve(n1 + n2 + n3 + n4));
}
TypeScript抱怨无法将number | Promise<number>
分配给Promise<number>
。
我已经看到一些使用infer
来捕获函数的返回值的示例,但是我不确定如何在此处应用它。
如何告诉TypeScript我在这里拥有的信息以及返回类型必须匹配?
编辑:
我需要两种可能的类型,因为我对该接口的实现需要区分它们。如果我的界面仅使用T
,则会收到错误Type 'Promise<any>' is not assignable to type 'T'
。这是一个简化的版本:
function monitoredOperation<T>(operationName: string, operation: () => T | Promise<T>): T | Promise<T> {
let onSuccess = (value: T): T => {
broadcast("finished");
return value;
}
let onFailure = (error: any): never => {
broadcast("failed");
throw error;
}
try {
let result = operation();
if (isPromise(result)) {
return result.then(onSuccess, onFailure);
} else {
return onSuccess(result);
}
}
catch (e) {
onFailure(e);
}
}
答案 0 :(得分:2)
我不确定| Promise<T>
会带来什么。没有类型,从类型角度来看,该函数的行为实际上是正确的。 monitoredOperation
返回回调返回的内容,无论是Promise
还是其他方式:
interface MonitoredOperation {
<T = any>(operationName: string, operation: () => T): T;
}
class X {
private monitoredOperation!: MonitoredOperation
public addNumbersAsync(n1: number, n2: number, n3: number, n4: number): Promise<number> {
return this.monitoredOperation("addNumbers", () => Promise.resolve(n1 + n2 + n3 + n4));
}
}
如果您想将Promise
保留在签名中(可能是用于文档说明,提示特殊的Promise
行为),重载会更好地工作:
interface MonitoredOperation {
<T = any>(operationName: string, operation: () => Promise<T>): Promise<T>;
<T = any>(operationName: string, operation: () => T): T;
}
class X {
private monitoredOperation!: MonitoredOperation
public addNumbersAsync(n1: number, n2: number, n3: number, n4: number): Promise<number> {
return this.monitoredOperation("addNumbers", () => Promise.resolve(n1 + n2 + n3 + n4));
}
}