第 44 条:比起直接用 any,更推荐用更具体的替代类型 
要点 
- 每次使用 
any时,都要想清楚:是否真的允许传入任何 JavaScript 值? - 如果有更精确的方式表达你的数据,比如 
any[]、{[id: string]: any}或() => any,就优先使用这些方式,而不是直接用any。 
正文 
any 类型代表了 JavaScript 中所有可能的值,这个范围非常大:
- 所有数字、字符串、数组、对象
 - 正则表达式、函数、类、DOM 元素
 - 甚至还包括 
null和undefined 
换句话说,用 any 就等于完全放弃了类型检查。
所以当你写下 any 时,不妨问问自己:
“我真的想接受任何类型的值吗?传一个函数或正则表达式进来也可以?”
很多时候答案其实是 “不行”。这时候就应该换个更具体一点的类型,来保留一定的类型安全性。比如:
ts
function getLengthBad(array: any) {
  // Don't do this!
  return array.length
}
function getLength(array: any[]) {
  // This is better
  return array.length
}后面这个版本用的是 any[] 而不是 any,好处有三点:
- 函数里对 
array.length的访问会有类型检查; - 函数的返回值会被自动推断为 
number,而不是any; - 调用 
getLength时,TypeScript 会检查传入的参数是否真的是数组; 
ts
getLengthBad(/123/) // No error, returns undefined
getLength(/123/)
//        ~~~~~
// Argument of type 'RegExp' is not assignable to parameter of type 'any[]'.
getLengthBad(null) // No error, throws at runtime
getLength(null)
//        ~~~~
// Argument of type 'null' is not assignable to parameter of type 'any[]'.如果你期望的参数是数组组成的数组,但不关心里面的具体类型,可以用 any[][]。
如果你期望的是某种对象类型,但不知道里面的值具体是什么,可以用:
{ [key: string]: any }- 或者 
Record<string, any>(作用一样,写法更简洁) 
ts
function hasAKeyThatEndsWithZ(o: Record<string, any>) {
  for (const key in o) {
    if (key.endsWith('z')) {
      console.log(key, o[key])
      return true
    }
  }
  return false
}你也可以在这种情况下使用 object 类型,它包含所有非原始类型。不过它有点特殊:你可以枚举这些对象的键,但却无法访问它们的值。
ts
function hasAKeyThatEndsWithZ(o: object) {
  for (const key in o) {
    if (key.endsWith('z')) {
      console.log(key, o[key])
      //               ~~~~~~ Element implicitly has an 'any' type
      //                      because type '{}' has no index signature
      return true
    }
  }
  return false
}在 TypeScript 中,遍历对象类型特别棘手。第 60 条会更详细地讲解如何绕过这个问题。
如果你期望是一个函数类型,就尽量避免使用 any。这里有多种写法,取决于你希望定义得多具体:
ts
type Fn0 = () => any // any function callable with no params
type Fn1 = (arg: any) => any // With one param
type FnN = (...args: any[]) => any // With any number of params
// same as "Function" type这些写法都比 any 更精确,因此更推荐使用。注意在最后一个例子中,使用了 any[] 作为剩余参数的类型。这里用 any 也可以,但精确度会更差一些:
ts
const numArgsBad = (...args: any) => args.length
//    ^? const numArgsBad: (...args: any) => any
const numArgsBetter = (...args: any[]) => args.length
//    ^? const numArgsBetter: (...args: any[]) => number注意这些函数的返回类型是不同的。剩余参数可能是 any[] 类型最常见的用法。
如果你只想表示“这是一个数组”,但不关心里面的元素类型,可以考虑用 unknown[] 替代 any[]。这更推荐,因为它更安全。关于 unknown 类型的更多内容可以参考第 46 条。
关键点总结 
- 每次使用 
any时,都要想清楚:是否真的允许传入任何 JavaScript 值? - 如果有更精确的方式表达你的数据,比如 
any[]、{[id: string]: any}或() => any,就优先使用这些方式,而不是直接用any。