TypeScript 中处理 unknown 类型需通过运行时检查与类型守卫结合实现安全类型收缩;常用方式包括 typeof、instanceof、in 操作符及返回 obj is T 的自定义守卫函数,如 isUser,确保编译器在分支内识别具体结构。

TypeScript 中处理未知类型(unknown)的类型守卫,核心是通过**运行时检查 + 类型断言组合**,让编译器确认某个 unknown 值确实属于特定类型,从而安全地访问其属性或方法。
用 typeof、instanceof、in 或自定义函数做类型收缩
unknown 是比 any 更安全的顶层类型——它不允许任意访问属性或调用方法,必须先“缩小范围”。常见守卫方式:
-
typeof:适用于原始类型判断("string"、"number"、"boolean"、"function"等) -
instanceof:适用于类实例(如err instanceof Error) -
in操作符:判断对象是否具有某属性("message" in err),常用于区分不同形状的对象 -
自定义类型守卫函数:返回
arg is T形式的布尔值,TS 会据此收窄类型
写一个可靠的自定义类型守卫函数
例如,想安全地处理一个可能是任意结构的 unknown 值,并确认它是带 id 和 name 的用户对象:
function isUser(obj: unknown): obj is { id: number; name: string } {
return (
typeof obj === 'object' &&
obj !== null &&
typeof (obj as any).id === 'number' &&
typeof (obj as any).name === 'string'
);
}
// 使用
const data: unknown = { id: 123, name: 'Alice' };
if (isUser(data)) {
console.log(data.id.toFixed(0)); // ✅ TS 知道 data 是 { id: number; name: string }
}
注意:obj is T 是类型守卫的关键签名,它告诉 TypeScript:只要函数返回 true,参数就一定是 T 类型。
立即学习“Java免费学习笔记(深入)”;
结合多重守卫处理混合未知输入
实际中,unknown 可能来自 API 响应、JSON.parse、事件 payload 等,结构不确定。可用嵌套守卫逐步识别:
function handleInput(input: unknown) {
if (typeof input === 'string') {
return input.toUpperCase();
}
if (Array.isArray(input)) {
return input.map(String);
}
if (isUser(input)) {
return `User: ${input.name}`;
}
if (input && typeof input === 'object' && 'status' in input) {
return `Status: ${(input as any).status}`;
}
return 'Unsupported input';
}
每个 if 分支都构成一次类型收缩,后续代码在该分支内可直接使用收窄后的类型。
避免常见陷阱
-
别直接用
as强制断言:绕过类型检查,失去守卫意义;应先检查再断言,或封装为守卫函数 -
typeof null === 'object':所以判断对象类型时务必加上obj !== null -
对象属性检查要谨慎:用
in比obj?.prop !== undefined更可靠(后者对undefined属性不敏感) -
守卫函数必须有运行时逻辑:纯类型断言(如
return true as const)不会触发类型收缩


















