变量、原始类型、字面量类型与类型推断
TypeScript 的日常使用从 JavaScript 值开始。类型标注应补足推断无法表达的契约,而不是把每个局部变量重复标注一遍。
1. 声明与推断
const siteName = "Knowledge Base" // 类型通常是字面量 "Knowledge Base"
let requestCount = 0 // 类型 number,可重新赋其他 number
function multiply(left: number, right: number) {
return left * right // 返回类型推断为 number
}
优先 const,需要重新绑定时使用 let,避免 var 的函数作用域和提升陷阱。const 只禁止变量重新绑定,不会自动冻结对象内部。
2. JavaScript 原始值对应类型
| 运行时值类别 | TypeScript 类型 | 关键点 |
|---|---|---|
| 字符串 | string |
使用小写 string,不是包装对象 String |
| 双精度数值 | number |
整数与浮点数共用;精确整数边界是 Number.MAX_SAFE_INTEGER |
| 大整数 | bigint |
如 9007199254740993n,不能与 number 直接混算 |
| 布尔 | boolean |
true / false |
| 唯一标识 | symbol / unique symbol |
unique symbol 可形成名义化键 |
| 缺省 | undefined |
常由未赋值、缺少参数或可选属性产生 |
| 空值 | null |
在 strictNullChecks 下是独立类型 |
const precise: bigint = 9_007_199_254_740_993n
const key: unique symbol = Symbol("key")
const empty: null = null
3. 字面量类型与联合
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"
type RetryCount = 0 | 1 | 2 | 3
function request(method: HttpMethod, retries: RetryCount): void {
console.log({ method, retries })
}
request("GET", 2)
// request("PATCH", 2) // 编译错误:不在联合中
字面量联合同时提供补全和穷尽检查,很多场景比普通 enum 更轻量,因为它不额外生成运行时对象。
4. any、unknown、never 与 void
any:退出类型检查
any 可传给几乎任何类型,也允许任意操作;它会把不确定性扩散到调用链。迁移旧代码时可暂用,但要隔离在边界。
unknown:安全的不确定值
function format(input: unknown): string {
if (typeof input === "string") return input.trim()
if (typeof input === "number") return input.toFixed(2)
return JSON.stringify(input)
}
任何值都能赋给 unknown,但使用前必须收窄。API 响应、JSON.parse 包装层、消息队列内容应从 unknown 开始。
never:不可能出现的值
function fail(message: string): never {
throw new Error(message)
}
never 表示函数不会正常返回,或联合类型已经被穷尽。它不是“没有返回值”;普通无返回值函数使用 void。
5. 空值与可选链
type Profile = {
nickname?: string
}
function displayName(profile: Profile | null): string {
return profile?.nickname?.trim() ?? "Anonymous"
}
?.在左侧为null或undefined时短路。??只在左侧为null/undefined时取默认值;||还会把0、""、false当作假值。- 非空断言
value!不做运行时检查,应只用于已有外部不变量且能证明的场景。
6. as const 与 satisfies
type Route = {
path: `/${string}`
method: "GET" | "POST"
}
const healthRoute = {
path: "/health",
method: "GET",
} as const satisfies Route
as const 让字面量保持窄类型并递归标记字面量对象属性为只读;satisfies 检查值是否满足目标类型,同时保留表达式自身更精确的推断。它们仍不冻结运行时对象。
7. 类型断言的使用顺序
优先级从高到低:
- 让控制流自动推断。
- 写类型守卫或断言函数。
- 改进第三方声明。
- 在已经由运行时规则证明时使用单次
as。 - 避免
as unknown as T双重断言,它通常是在掩盖不兼容。
8. 练习
实现 parsePort(input: unknown): number:接受数值或十进制字符串,拒绝 NaN、非整数及 1–65535 之外的值。这个练习同时覆盖 unknown、收窄、数值语义和运行时验证。