该做什么和不该做什么

泛型类型

Number、String、Boolean、Symbol 和 Object

❌ 永远不要使用类型 NumberStringBooleanSymbolObject 这些类型指的是非原始装箱对象,它们几乎从未在 JavaScript 代码中得到适当使用。

/* WRONG */
function reverse(s: String): String;

✅ 请使用 numberstringbooleansymbol 类型。

/* OK */
function reverse(s: string): string;

使用非原始的 object 类型 (在 TypeScript 2.2 中添加) 而不是 Object

泛型

❌ 永远不要有一个不使用其类型参数的泛型类型。在 TypeScript 常见问题页面 中查看更多详细信息。

any

❌ 不要使用 any 作为类型,除非你正在将 JavaScript 项目迁移到 TypeScript。编译器有效地将 any 视为 "please turn off type checking for this thing"。它类似于在变量的每个用法周围放置 @ts-ignore 注释。当您第一次将 JavaScript 项目迁移到 TypeScript 时,这可能非常有用,因为您可以将尚未迁移的内容的类型设置为 any,但在完整的 TypeScript 项目中,您将禁用对程序的任何部分的类型检查 用它。

nY8T6GPjMwvDyOiS4tmoNBAI3KJCXqyLX/V0eOKPgxrLHQqNYHcM4yPCLN2F2FzDkcw/oarwJ+kaxpSGYNtflUQH+RLCsKQ9FW7BH92zau77ZmRDvcc8v6LknjRuMyrbUOf262T6LkFDRtH3DW63xxOvEXbRusQC7oplpXmXbbDGitMNhpRt4X9wzXzkg0g4hDZsOuWpRzDtHQZng4GCADCLGIJxA2aefBzBEpWKIhLP880N5vNeFcfD6+3vfW7Pts6Jh90UCUFWt8ekOC6U5WvwQCeUg34I/cMq2EdTg/0=

回调类型

回调的返回类型

v/UWR0l+smJc+Bq+CwAihao8jolwnl7vYkTxWHjO3f86q8XQujD2E6xQ9kDOKk25/RJPZwUeVNofNa601OzVhScxMApEb1tB6Nc3ThX+e3s=

/* WRONG */
function fn(x: () => any) {
  x();
}

mCcte0t5IHBNf4KhvZ5Utwcy6MouU3CMP08BbQMzuG4uKEgCzH7d20YxBugqA1Bt97g8bvdARwJP3S09rhF4rIvct8rATjre6pxsqvK023g=

/* OK */
function fn(x: () => void) {
  x();
}

Nm9dZK+u9XpVzDTjpNCnmt2fqV+P5x5JuFQ1qqJLF0UTC4Oeh7UfgHzIFhVOUOcgA6t7LXQZ0f5IJXrBDH7KUwe0c2ZsQDdYrd1e/QG3Mth4w9rmcDJqoyuO5mN/TQ1EUZRcuoJGyfLHR0vzcmXoL+kcOHMpof5ny2cyYSXVCSi2P/zOx+SsP9XF279/MkBUcuNVvF8wE4bfOorK13Nbub+hkZi7ZZb7ujdaUwhUtPw=

function fn(x: () => void) {
  var k = x(); // oops! meant to do something else
  k.doSomething(); // error, but would be OK if the return type had been 'any'
}

回调中的可选参数

D2FL1l+cd9Hx557We7xx0/c+xg9RrjnZRL4Ix0HWIdLe5z8qAPvE3LOGQLm8BhvJv84qwwM1fOzxmdbIXf+inYmuYFAhL7Fii7cxeVNTTA8=

/* WRONG */
interface Fetcher {
  getObject(done: (data: unknown, elapsedTime?: number) => void): void;
}

HaJBhT/q8sdHoCNm0F2JjxHJKgkz8bFXLKHvCWzpm2Ypg2/UjreVHOLzNDrchm1LcGQf4Q574yaCcJTXsILxxEpmrrOg0wP1metL6HAroAsfXpV8yFVzKtwSupqFWhuaysjdi71sQyfQWRYr41/FHlKVwGrARxhhf8dEMyPakvYFD9WTZq8iT3LkUW5Tv4KfU+37xq8piQHHT6EVmJL+LHU/DgM0VhumDPU3/9ND6I/LQWYuDf+5iR5qlmCLhiLwC9+h2YHSAdIZlWDAVg/d9rSdkIxGfDtjbNAZktZzrhNgn30F8Y/bF0OPMTGalc5ucad6aQSfKlsxWRigktZ2o5OTJrzBJ5JpA1S7CzIepPo+Cp96nvoOP46C1yGdT4saW0Bp00VFKQ2nTT6AP1Yvbjlh+VHh7zZjkB8HWcDQOSI=

pKFq+gnV2u0ZoEX3xRnD1B61cebaOAiaBb0jZrzzQpn2baUiZNJbFrxAB9izWL9B

/* OK */
interface Fetcher {
  getObject(done: (data: unknown, elapsedTime: number) => void): void;
}

重载和回调

vGb3zYcUK9/gmk6DFdjhSqlsckkGvGvngxd47BZHeCo/W7I9xuZpAYEj6Wod9OeAG6zIQZ/U9yyNoFC4Xo/0hw==

/* WRONG */
declare function beforeAll(action: () => void, timeout?: number): void;
declare function beforeAll(
  action: (done: DoneFn) => void,
  timeout?: number
): void;

arNmH+FKcP49LZ7YVZks63QeB+Ym2kKjUC8cV+d99wG5jzbZeSBc49gPDlA4eeUvP86eXSRk5GXBjqSTFLCCJg==

/* OK */
declare function beforeAll(
  action: (done: DoneFn) => void,
  timeout?: number
): void;

Nm9dZK+u9XpVzDTjpNCnmt2fqV+P5x5JuFQ1qqJLF0Vea2lRFPndl6FO3VygUdUdD86zrCPjmx3AeeuHzc00VJA+ENxOrh9NIjvEodgG/9IZgsplHczrUAZ9PG4wFM6be54RiW5hhFYbGUMUnxG2cjI/ynCoEErRzOhsx+PMJH2ihzBZGdH1t+Pip4oL01n/wGBn1Jua8DTeEnv3XVmKgCFeRGgsulOOOEbI18XbgAzoeqOKh8lZABz/Um8agZxhff1FEyyB3RnwrD8MrvX22jUWu6b6h4IWKYrmyfv2ZjM=

函数重载

排序

jFIDNuIbQocmkqBJDbgCEMo0StXX6l48NkQNgwfLRRs2GOyCkre6zVBrl0wCd9tAOzjgLxA7H+9Pdhquvtqiig==

/* WRONG */
declare function fn(x: unknown): unknown;
declare function fn(x: HTMLElement): number;
declare function fn(x: HTMLDivElement): string;

var myElem: HTMLDivElement;
var x = fn(myElem); // x: unknown, wat?

xPkEySuIsuDkra/QEYwisk1/6TFtABCcaf0l5QDIPBKb88pY5RsyuuWIWVdFE/aBXlTplDLXf+YAF227OXPuwT9HQN4fx1qnvbSGO3CyjXQQGrdNBwFieg53umn5C+ck

/* OK */
declare function fn(x: HTMLDivElement): string;
declare function fn(x: HTMLElement): number;
declare function fn(x: unknown): unknown;

var myElem: HTMLDivElement;
var x = fn(myElem); // x: string, :)

Nm9dZK+u9XpVzDTjpNCnmt2fqV+P5x5JuFQ1qqJLF0U2yRkQ1g7jwajmvAhVXkMUnArVaUm0zkVInzYDDnRwiD9LAOL8d9RmsoSatMznwAdPIyFdrMOioI4dYYySQJhzr2TIEGIWEjrt23D5lWhbwnQID4p5SqxfK1JqEbEXrdBh15mPZSNlPuak12FX08qyWPGSdI1LzlRS+hPoUVLfau6+Pdo6NW+9ej8DUkIwCOOxpFC8xCZsr2uRRJ/Er6EgQncB+o/Brpa+/vZyfLJskLEkZ4EIJc8+kcYjg6Ayelg=

使用可选参数

vGb3zYcUK9/gmk6DFdjhSmHyYdAV6DL/Px0VscHxngyM8+ub2LZqkEUZ/KmH1IpxmGMHJHCjp8Hrr3UTuFwriQ==

/* WRONG */
interface Example {
  diff(one: string): number;
  diff(one: string, two: string): number;
  diff(one: string, two: string, three: boolean): number;
}

h/zHjvR4Hsp8oXyrYWIy73aJw0jYbBkIQZLqXNzGrxkN2XGJi1/qMJKDspsarPjD

/* OK */
interface Example {
  diff(one: string, two?: string, three?: boolean): number;
}

itZvtHIg5E58/7QzOboYF0AyWRdD6/RhcnYunPNSOIv5OXr3YYpBCgIZ4ervJMKwq3oYMYrFEbwaYYYExp2rNAMp59NKFUlbcrrkDtRctUBROBI1h8176k9P9V0tRyt5Zn2ailqxRTMrSca6tlku0g==

Nm9dZK+u9XpVzDTjpNCnmt2fqV+P5x5JuFQ1qqJLF0XnL+QYiPInhslNnwM0RIiYSgvAbh3xKakdJtP4WDfxnA==

ec3l3E9Ah0H18bY8QNhE/rr9rMvevNN3ZZnJL7EoK6X0z8yFop3qTaYqiYRwupvWW9dmn9PvMSftP4k5dDGiR4tcz4/LcfFCU0ETCxzm1HLWRFiV5/RoVTDy2cqXKNZxDtgbh9BAnCxR9hfIz/Sl1jBm8998s8yyTbU7scKKXgHpbBGb8Z6HHaAQu1Qao0OnYxExaotX20NfPY9+JHUG6Sd4YtyxceBvDuVG2IBeE3LeJu1AZc3IqMIMeRFRKIqw6OmDsFY+RDEONOH/nMxk429bpevaCIrG/iQLhO0t//2MBBKCfY4+1lc2HSCstgRX

function fn(x: (a: string, b: number, c: number) => void) {}
var x: Example;
// When written with overloads, OK -- used first overload
// When written with optionals, correctly an error
fn(x.diff);

+VaP8l2L6/eb6XvpBIpcUEx5vsnoL8cHx7yT21zK6NDkzJlaa//x+ZEs05L0URQHLmQ+nrTqt0xfQWQ2S6JdCW+lrxff0xgUfyMu6QW3t0ZjUYUzQ9X/tJZUcqSbYgh0Pdqfun9uaJw4uMnc9fw5sM5uf5pZol7jO9krUFv4UK+0nnNWDvLdMpDFIiC9MYJ/IpPis/bvgX0/4KSeNiTBNb7adxjkcmV8BSQTn84b6KGVLw3KD/N7R0oXiZ53UqzVctfhbZZ3xyYfWNyqeqplFiRzGTNOIITqZ5c5FNZ0BwnLadt1bZZqEFtrSiF3gIoEjsNosSX+o/b1vlm5foRU69ydkxsfa6/T6tlVKiXEzNll8y6SSe4eO4WC5NT1JN9P2NSuPx4z3z234wuWERf01zmHzUnL2bGkssRfTqgeshU=

var x: Example;
// When written with overloads, incorrectly an error because of passing 'undefined' to 'string'
// When written with optionals, correctly OK
x.diff("something", true ? undefined : "hour");

使用联合类型

U0f+F+JQz5C7G8ZTQZZjaS/D6FHTcWkYNePZewHGIeLus4A1CKuqxWR9HyrA/HaOvNxyLJ7dU4jnQNbSmaq74SLUZd7JKOZMIBJq+L6YHJ8=

/* WRONG */
interface Moment {
  utcOffset(): number;
  utcOffset(b: number): Moment;
  utcOffset(b: string): Moment;
}

h/zHjvR4Hsp8oXyrYWIy75aZX1yX9Tx/zdR1yNnl8yhWrQ27NWj6xri67j45+edc

/* OK */
interface Moment {
  utcOffset(): number;
  utcOffset(b: number | string): Moment;
}

s5LoDfGjvBxoULHJFEwwykwtEbMEupsg9z3tvOkZSCJjTVcE4YscR4LTT9SdLOahxlMmWCev0ywxWfBy8dj6gR+nJNRarqoUwNyBzUjHOa2Ahko7tYRCIEvB4vwG1Xde84ZcECsepvphw8J8Qh9+iw==

Nm9dZK+u9XpVzDTjpNCnmt2fqV+P5x5JuFQ1qqJLF0U6bscx7XYUrArtqqPcwvPxYy5owukgxzlCPYoUgHkioxvx/pOMXaxnuqZeE94BsJwXPPKMPrKK0hglTjWckUk9qcQmZcgMPAQ1ikXSaC6Vww==

function fn(x: string): void;
function fn(x: number): void;
function fn(x: number | string) {
  // When written with separate overloads, incorrectly an error
  // When written with union types, correctly OK
  return moment().utcOffset(x);
}