TypeScript 06:函数类型与四大特殊类型
有 JS 基础即可阅读。建议先读第 01~05 课。
1. 函数的「形状」也是一种类型
参数列表 + 返回值 = 函数类型,可以像 interface 一样起名复用:
type Handler = (msg: string) => void // 参数名只起文档作用,类型才是重点
用它标注「接收函数的函数」,传回调时回调的参数自动获得类型(上下文推断):
function repeat3(action: Handler) {
action('a')
action('b')
}
repeat3((msg) => console.log(msg)) // msg 自动是 string,不用写注解
写回调从不标参数类型的便利,全部来自这条规则——签名定在「接收方」,调用方自动跟随。
2. void:调用方「不该用」返回值,不是「必须没有」
const logs: string[] = []
const logger: Handler = (msg) => logs.push(msg) // push 明明返回 number,却合法
void 是站在调用方视角的约定:「返回值没有意义,别用」。所以 () => void 能收留各种「有返回值的函数」——事件处理、forEach 回调都靠这条宽松规则。
3. 函数重载:一个函数,多套签名
场景:参数组合不同、返回类型不同。写法 = 多条签名声明 + 一条实现,调用方只看得到声明:
function pad(value: number, width: number): string // 数字补零
function pad(value: string): string // 字符串原样
function pad(value: number | string, width?: number): string { // 实现,调用方看不到
return typeof value === 'number' ? String(value).padStart(width ?? 0, '0') : value
}
pad(7, 3) // ✅ 匹配第 1 个签名
pad('hi') // ✅ 匹配第 2 个
pad('hi', 5) // ❌ No overload matches this call
pad(1) // ❌ 数字版必须给 width
重载的价值:把「哪些参数组合合法」显式列出来,而不是用一个宽泛的联合签名把非法组合也放行。日常业务少写(参数对象/联合 + 收窄常够用),但库源码大量使用,要能看懂。
4. 四大特殊类型辨析
| 类型 | 一句话 | 典型来源 |
|---|---|---|
any | 放弃检查,读写都不查 | JSON.parse、无类型的第三方库 |
unknown | 未知,用前必须收窄 | 外部数据的安全形态 |
void | 没有有意义的返回值(调用方视角) | 无 return 的函数 |
never | 不可能有值 | throw 函数、穷尽检查兜底(第 04 课) |
const a: any = JSON.parse('{}') // 读写都不查,危险
const u: unknown = JSON.parse('1') // 先收窄再用,安全
function log(msg: string): void {} // 调用方别用它的返回值
function fail(msg: string): never {
throw new Error(msg) // 函数永不正常返回 → 推断为 never
}
// fail() 之后的代码不可达,TS 知道
记住两个极端,四个类型就串起来了:
unknown最宽(任何值都能赋给它);never最窄(它不能赋给任何类型)。any是「跳过检查的未知」,void是「为空的返回」。
5. 高频报错速查
| 报错 | 人话 |
|---|---|
No overload matches this call | 参数组合不匹配任何一套签名 |
This expression is not callable | 把非函数当函数调了 |
Type 'X' is not assignable to type 'never' | 穷尽检查或类型冲突抓到了你 |
Expected 2 arguments, but got 1 | 参数个数不对(对重载同样生效) |
1116



被折叠的 条评论
为什么被折叠?



