类型推断

在 TypeScript 中,有几个地方在没有显式类型注释的情况下使用类型推断来提供类型信息。例如,在这段代码中

let x = 3;

x 变量的类型被推断为 number。这种推断发生在初始化变量和成员、设置参数默认值以及确定函数返回类型时。

在大多数情况下,类型推断很简单。在接下来的部分中,我们将探讨如何推断类型的一些细微差别。

最佳常见类型

当从多个表达式进行类型推断时,这些表达式的类型用于计算 "best common type"。例如,

let x = [0, 1, null];

要推断上例中 x 的类型,我们必须考虑每个数组元素的类型。在这里,我们为数组的类型提供了两种选择:numbernull。最佳通用类型算法会考虑每种候选类型,并选择与所有其他候选类型兼容的类型。

fjuyIUdLtIiNZAckTMJ4o8LtUAbMGICLJ+D7NlzrwbD8KbqKQi/Seb5YdtUW3eCRNtzuTNN7W2TX8JWBPyJV7s5HsDk1UXjWlWSupCTjhP1aG29ReJboOcGVjYVtvoND349w/lv42oA4DQHgmNx2SpAfM9GtCUcziwd42vH5GMrpijQgYLb9x2Vxup/GJcCH3LC1wqvk0e2KGiNEHRX9+bPNHqurzZV8l2s9dqgH/kwKZ2YLUIzImpckW5LZdRfQ

class Animal {}
class Rhino extends Animal {
  hasHorn: true;
}
class Elephant extends Animal {
  hasTrunk: true;
}
class Snake extends Animal {
  hasLegs: false;
}
let zoo = [new Rhino(), new Elephant(), new Snake()];

jNLauEhywy/cytMnqtVI9TgeY8uZ0Rw1SQ+0xbjqwmIBz+mQM0wj6t6A/90/UPJu8i+M64ssyS7EO8/G6j70XDK4edOsj3mrldfoo3Km6lesWYrhN0japGRBFL97v+m1LEMvOWUUhKmdJJSsCOfZc1StB/zccAXVLzcSUSidXAM2G5TW/HkRwvpozhQYFpDal8zza9cTpNwXKpbz1i9f4hfaLvRyyRa0NNyGtfmFX39LjdduCHz1Q5LTGPWq+aItUEXQ13udxBf2raHlVkdBHR28/bgucM21hS1jYSAHyPBXg3PxvPuLd0SfCxGI6nX0mFXpp0owAEsWWD9vWIf7t+sfTI9ILZEO9+hoR1Jsnt7plGhGUbrdbeh5wB0F9QA9KjICAnHY4aqxuaPeWGMlC4opSOPEs8zeiKmf0mnGTWc=

class Animal {}
class Rhino extends Animal {
  hasHorn: true;
}
class Elephant extends Animal {
  hasTrunk: true;
}
class Snake extends Animal {
  hasLegs: false;
}
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];

gmCWjW6mpDa8t58bAyo3wwGxEnScktHRijoFjroP3odIgvmUtZc4zSO1KfIpPpnPT4YpJMkBLh1pDtNh66vp1EetJuFAuomzxWBnYxZN9418l5pa4W2X8vF3TWH85nPIM7hZlYP8owPz+djBJOyuBqb0RfzcFUM0/LmDBlQrbD4=

上下文类型

gxCK5EVjlHWrXIb9Kq85UuZHS7hFDNErOyFDQKtDMgm528GGgwFzUTo0cQFMWwJUoWELCG+K+ofu9+xVBBrMaMuG93GqTPErCyxzg714t/7DVYWnc8hQIDWbcOSTt2UR8ctJa/q/eA+PHx3E/+u5NpX3rbudUWtqI/ORk789M1bukBpR5+IvLHGonlvCNnGg2KgYzH536imfq6Ky/OsI2LkP/plN/uA4BZs8Xj91HxKvmSIyi/u7qd8+00oLoOfpcle1vuy34mAliRT1EIb1mw==

window.onmousedown = function (mouseEvent) {
  console.log(mouseEvent.button);
  console.log(mouseEvent.kangaroo);
};

9GtSxxttqIi/I5pCKn8JcXiaE+pkeZpxSf5TzJI9f2KbOkW3rE5EMdk07u95Ip9WDjqOORml3GGRreyIqSRuRXS48zbACnZQ6aKRV6qsrocY2cAj4QviVDhegOdfVziyltyBnSQYNWsJvo+KLmnSvMuRKCSHoK9u2Ov6217VwaCPPV8ra7eY3ShHy00+XVdaYIZ752UizJWIK9U+otKUsCppfXNxJ3PbYQ0m3EOdA5VWYeYnm0X0s5BrwGHmW6G+IY+xGZ6ya/QsuxanFxtUp+Oqgxf32QOkrOyZ7jAmp1qflDLSQ3dvBhblaS9ynmyo1bNfIZg7R+eD7fEqMCNpUnDX/DMUw3F/0zme+L2MILVrk5ZUvhiguFj59IInUxaweIEfQoRO2BK0Liitz87Q1l2+UynwbzP9VZkhZfMGU04TLUiJoJ1n0n5ypTpyrEU5XL0ZLV7E8IpPSoNols7AU2815qTv2z0gvLtiwfp5iv4=

fjqIsGLgTJPtdRvR8C1yX1M0sJ8OYT7BkCVSo49DBRcjGUCg5/9WO3J0japZpvNIjUYIOly0o3mGLjD6sDWTx/wh1H+3KyWPG20jl7lPapAzGWouEgNjhLSvKo8ylODH

// Declares there is a global variable called 'window'
declare var window: Window & typeof globalThis;

// Which is declared as (simplified):
interface Window extends GlobalEventHandlers {
  // ...
}

// Which defines a lot of known handler events
interface GlobalEventHandlers {
  onmousedown: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
  // ...
}

hogQqlx7NRPwC1DwocVTe4Pqh6uJrvHBq0/I46dYC+gOUutZYDuctR/RclJdBHm8LDhaRaAXVxRD2cVB3fPwBBn0VKnM0+RlfB5Fq5AiJZQ=

window.onscroll = function (uiEvent) {
  console.log(uiEvent.button);
};

6kQyBuYH25Gc73iqIisoQi0RYZqtpgqiFqzmz8EodCsRMQMRy09GzIa1kdKqY8W37hdQT2SBnhb4sdMVEYFrWy9kutTK52HrO+gU4Rfl533lSX0mXq3aWTERivi4RZ9Prbo/zop+6RF/2O0SpF88ffrXPVC1mltuEMSyPfYSn3QQ27Bs398Nli0FrJVSpBgHr0X7bSdCLQaxM0C4jT4QLZYOEqxjGlWoH7pwk557ztWm8TnMCklbj1RAjPid0LhlnUSvnPOLXwXb5n42xwNV5rAVSr375WitPJvD9P3myo9puFvLH+IBK6SsBN3bph4dd97LtNBzykC99Gu130HiezDWBiuAJxgTcPWpCfnTsw82GW+wpB1ojkPO8vn5+8CEbM/Ko3cZ0HYFDJoffSH0hIsiSOju4Nwp+g/uAu8QdJLwxD3SQuvDUQpkCLVy3KFbqnpWpTAGmEqcho4Q9KEFWBUc+6yagNTL6JlZRw5aNrHDyS7dDdbNUggxb05Et+HuDGwPJWRvWoVRV1/FsWJE0A==

5vt7c+llVZhRgYXbGt7spUKMS37lQgpELsSv8jJBErvTiwkDSPi64Jc5yyY+bVeQznn1TFXTdiDFI7yUHFQ0ElNQ9LSAWq919DqgGw/IRNeqUJJ6qqxQyffxZ+U70WRD/JOVUzQgLsNjDRRMZJwTuaBlQb+DqYHr9a8nI4jLMAvxB6R/Vgm3KGNoL6/lBmlhxoCaixNnMWEc38HcKwqm69oaJZViGSF6FzCl4jayXVjginsOrRfHpsev1SlCHR0g7Ibrrrn8gLXw9u0CG/iqTwkSEJLkaqF4KFoaG0kyyr0QUKLJ/zGDrJfew+5UK2xh

const handler = function (uiEvent) {
  console.log(uiEvent.button); // <- OK
};

8adr96EnfIqkjAppqe9drxXrTcz1ij0VHtlAv6mC41YVVKsEkIf2goMuBKp/D+ZJCb7aBQhK6vt8JISPhRtsFqCwQZUIRZcqjr/IUIlrvplZE3hSRM7bultMEh+7Ocp0

window.onscroll = function (uiEvent: any) {
  console.log(uiEvent.button); // <- Now, no error is given
};

q32xSqt3895ch1ceJEQcAZ14A8URNYliT2DbAFon2fgxc7iPQwSRAPPmapNlXFjFw65BYbmp3Dv4ZXbq8Ubsk4tim1ZRsF8O40eE7NdQV4qV672WxHIB9R2DVUyp4fTKxoChb6pP8WXirSvxf5ysdV/8NPQPa1nmGOsOjtqbqGI=

jIlRA8LH7NY8ZQilCV4TDW9Vj/qxr5HsQP9cvNqlx/0l95MIub0wuE9hWbCs8AOucpOZVD8YvKLgl74L74QFvWDSkZUECNwS2aCSSxCvPxKIui/lz+F0zNDAwYZaqYwx4vGAC4/QoCK0w4fw/T/JyfZ0T1fZYN9TWAvME7GxJ5xNdzKUha7kHZSRaFQVyFDi8lg+14I1x0F4xUAZ4GEHFyNPGag58T86RsQ1C3sxfa0v0AIbHapCaBw0kzYMQh/pn0JCgWwYn58qh2fP/GoPijwEjqbPGiMoANFNDIr00X3T2k0MTlOBgeMBInM5Z1YdnhFkajLcHaVs4g/HhDENxA==

class Animal {}
class Rhino extends Animal {
  hasHorn: true;
}
class Elephant extends Animal {
  hasTrunk: true;
}
class Snake extends Animal {
  hasLegs: false;
}
function createZoo(): Animal[] {
  return [new Rhino(), new Elephant(), new Snake()];
}

qAvdjr7k2TFptR7Flfde428pbpmvchD9B8SkH0YoElH5+kwoMSeoiTCIemM0IsoECv9TYXRz+YqYuZ8CFdjE26N8OXIBskuREfeNvac2iy4e3uCF/rtNDMcXRkzzJlgutWH0lXDtfmzJFa4P9GFiqmhR/2oD78/OI/dnq4912ZEXMwqyf4pfHmoABue7SCkhsTEuj0sLF+bilGKqtGcXrjG9gDWDOtkTQ4k9mwN7xFRK6yKPJyMtAnPX90Kcm93jpxRam54QIofcyuVazvZToeiWCQ2PrxwcRCiKL3ALcvwO8m/PFDnJRtuTf566mzG/