下面是一个非常基本的设置,其中我有一个App处理 HTTP 请求的类(想象一下,HTTP 服务器的代码未在下面显示)。
interface CallbackError {
error: string;
}
type HandlerCallback = <T>(payload?: CallbackError | T) => void;
type Handler = (callback: HandlerCallback) => void;
// omitted code here is a server that calls handleRequest on a request
class App {
public constructor(private router: Router) {
this.router = router;
}
private handleRequest = () => {
this.router.handleRequest(this.sendResponse);
};
private sendResponse: HandlerCallback = (payload?: any) => {
// do something
};
}
当一个请求进来时,在类handleRequest上被调用。Router中的路由Router只是一个被调用的回调,仅此而已,而且这个回调的类型是Handler. Handler将另一个回调作为参数,类型为HandlerCallback.
class Router {
private routes: Handler[] = [];
public addRoute = (callback: Handler) => {
this.routes.push(callback)
};
// the request is handled by simply calling the callbacks added
public handleRequest = (callback: HandlerCallback) => {
this.routes.forEach(cb => cb(callback))
};
}
interface User { id: number }
const handler1: Handler = (callback) => {
if (Math.random() > 0.5) {
callback({ id: 1 })
} else {
callback({ error: "error" })
}
}
const handler2: Handler = (callback: (payload: CallbackError | User) => void) => {
if (Math.random() > 0.5) {
callback({ id: 1 })
} else {
callback({ error: "error" })
}
}
const router = new Router();
router.addRoute(handler1)
router.addRoute(handler2)
正如您在上面看到的,我定义了两个“路由”,即Handler路由器要调用的两个回调,它们每个都带有一个回调参数类型HandlerCallback。我的问题与如何键入后者的回调有关。在handler1中,我将参数隐式类型化,因此HandlerCallback使用泛型类型的定义对其进行类型化。在 TS Playground 中,如果您将鼠标悬停在每次出现的callbackin 上handler1,您会看到不同的类型。
如果您执行相同操作并将鼠标悬停在对 in 的两个调用上callback,handler2它们的类型与在参数中显式键入的类型相同。
所以我的问题是
-在handler1,为什么当您将鼠标悬停在调用上时 TS 不显示相同的类型callback?特别是, inhandler1是callback使用 type 的User参数或 type 的参数调用的,那么为什么推断CallbackError的类型不是 is ?callbackCallbackError | User