函数参数双方差

比较函数参数的类型时,如果源参数可分配给目标参数,则分配成功,反之亦然。这是不合理的,因为调用者最终可能会得到一个采用更专业类型的函数,但调用具有较少专业类型的函数。在实践中,这种错误很少见,并且允许这样做会启用许多常见的 JavaScript 模式。一个简单的例子:

When comparing the types of function parameters, assignment succeeds if either the source parameter is assignable to the target parameter, or vice versa. This is unsound because a caller might end up being given a function that takes a more specialized type, but invokes the function with a less specialized type. In practice, this sort of error is rare, and allowing this enables many common JavaScript patterns. A brief example:

enum EventType {
  Mouse,
  Keyboard,
}

interface Event {
  timestamp: number;
}
interface MyMouseEvent extends Event {
  x: number;
  y: number;
}
interface MyKeyEvent extends Event {
  keyCode: number;
}

function listenEvent(eventType: EventType, handler: (n: Event) => void) {
  /* ... */
}

// Unsound, but useful and common
listenEvent(EventType.Mouse, (e: MyMouseEvent) => console.log(e.x + "," + e.y));

// Undesirable alternatives in presence of soundness
listenEvent(EventType.Mouse, (e: Event) =>
  console.log((e as MyMouseEvent).x + "," + (e as MyMouseEvent).y)
);
listenEvent(EventType.Mouse, ((e: MyMouseEvent) =>
  console.log(e.x + "," + e.y)) as (e: Event) => void);

// Still disallowed (clear error). Type safety enforced for wholly incompatible types
listenEvent(EventType.Mouse, (e: number) => console.log(e));

a05NP89fuVvdiV5s6Rt965xA7BEGUmc8j4VML1kHZ9L8BLLMIt4KSmY0xFk1wqvRNeMuV8AiDmvINSs80ZVKOz+HzbRVX4LDvtyBJhgsID03rS1g46rf8kcaovYHeN+wT/1U2qwvbqURgbTzAhlUEbS1Q6BW9Hr76vsmL39JdYqUN0kf+ZEm7lZtHw0Won7w+cdA02WjjzWFMqNe2xMa422yej1gNvSBSfXL2SAh/p6yeG+IsDMnXKZ3FkQ5HlllMTo8Anu+gF637fSObiNhpZ2pQM/m5E5z3HTpteSMJmOIG3Jz40Nu/hMZxT/lWIzKFhwuK6kjaQuF0gluXJlr34V64h0SFHzLHdxpMTXFH7IF8YLDBWEOunbPthHWWNlqtWRSmlKmL/Xoem4gutkH0FaWV+uEvOFY5dTknapEGrmDayjtmHIA73uIindY561kfKMDUk2Z+O6f9uTHRm9vTw==