我正在尝试在打字稿中定义类型安全的nodejs风格的回调。我希望将
err
定义为 Error
(如果存在)或 data
定义为 T
(如果不存在)。
export interface SafeCallback<T> {
(err: unknown): void;
(err: undefined, data: T): void;
}
const subscribe = <T>(callback: SafeCallback<T>) => {
let result: T;
try {
// result = something
} catch (e) {
callback(e);
return;
}
callback(undefined, result);
};
subscribe<{id: string}>((err, data?) => {
if (!err) {
console.log(data.id);
}
});
我明白了
'data' is of type 'unknown'.
data
中删除问号,我得到
Argument of type '(err: undefined, data: { id: string; }) => void' is not assignable to parameter of type 'SafeCallback<{ id: string; }>'
我尝试了在第一次重载中定义
err: Error
的两种情况,但它没有改变任何东西。
我还应该尝试什么吗?
谢谢!
也许有条件类型?
export type SafeCallback<T> = {
<errorType>(err: errorType, data: errorType extends undefined ? T : null): void;
};
const subscribe = <T>(callback: SafeCallback<T>) => {
let result: T;
try {
// result logic
} catch (e) {
callback(e, null);
return;
}
callback(undefined, result);
};
subscribe<{ id: string }>((err, data) => {
if (data !== null) {
console.log("data = " + data.id);
} else {
console.log("err = " + err);
}
});
编辑:刚刚看到@jcalz 回复。从他的回复中获取一些信息:
export interface SafeCallback3<T> {
<errorType>(...args:( errorType extends undefined ? [err: undefined, data: T] : [err: errorType] )): void;
}
防止在 catch 中抛出错误。
const subscribe3 = <T>(callback: SafeCallback3<T>) => {
let result: T;
try {
// ...
} catch (e) {
callback(e);
return;
}
callback<undefined>(undefined, result);
};
subscribe3<{ id: string }>((...args) => {
const [err, data] = args;
if (!err) {
console.log(data.id);
} else {
err.message
}
});