类型安全地处理 unknown
先收窄 unknown 值,再安全地使用它们。
类型安全地处理 unknown 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。
安全处理未知类型
将外部数据标注为unknown只是完成了一半工作。另一半是在使用前将其缩窄为具体类型。本课将介绍主要的缩窄技术。
function describe(v: unknown): string {
if (typeof v === 'string') return 'string: ' + v;
if (typeof v === 'number') return 'number: ' + v;
return 'other';
}
console.log(describe('hi'), describe(7), describe(true));使用类型判断进行缩窄
typeof守卫是最简单的工具。它可以将unknown缩窄为原始类型:string、number、boolean、function、object等。
function double(v: unknown): number {
if (typeof v === 'number') {
return v * 2; // v is number here
}
return 0;
}
console.log(double(21), double('no'));使用实例判断进行缩窄
对于类实例,请使用instanceof。它可以将unknown缩窄为具体的类,从而安全地使用该类的方法和属性。
function handle(v: unknown): string {
if (v instanceof Date) {
return v.toISOString(); // v is Date
}
return 'not a date';
}
console.log(handle(new Date(0)));使用属性存在性运算符进行缩窄
in运算符会检查对象上是否存在某个属性,从而缩窄对象类型的值。请先确认该值是非空对象,然后再检查它的键。
function getName(v: unknown): string {
if (typeof v === 'object' && v !== null && 'name' in v) {
return String((v as { name: unknown }).name);
}
return 'anonymous';
}
console.log(getName({ name: 'Ada' }), getName(5));自定义类型守卫
自定义类型守卫是一个返回类型为value is T的函数。当它返回 true 时,TypeScript 会在调用位置将参数缩窄为T。
function isString(v: unknown): v is string {
return typeof v === 'string';
}
function shout(v: unknown): string {
return isString(v) ? v.toUpperCase() : '?';
}
console.log(shout('hey'), shout(9));针对对象结构的守卫
自定义守卫特别适合验证对象结构。编写一个检查所有必需字段的函数,代码的其余部分就可以信任缩窄后的类型。
type User = { id: number; name: string };
function isUser(v: unknown): v is User {
return typeof v === 'object' && v !== null &&
'id' in v && 'name' in v;
}
console.log(isUser({ id: 1, name: 'Sam' }), isUser({}));JSON.parse 返回类似未知类型的数据
JSON.parse的返回类型是any,这会悄无声息地绕过安全检查。最佳做法是将结果接收为unknown,并在信任其结构之前进行验证。
function parseConfig(text: string): unknown {
return JSON.parse(text);
}
const raw = parseConfig('{"port":8080}');
console.log(typeof raw);验证解析后的 JSON
将JSON.parse与类型守卫结合起来,可以将不受信任的文本安全地转换为带类型的值。如果验证失败,请处理错误,而不要信任错误数据。
type Config = { port: number };
function isConfig(v: unknown): v is Config {
return typeof v === 'object' && v !== null &&
'port' in v && typeof (v as any).port === 'number';
}
const data: unknown = JSON.parse('{"port":8080}');
if (isConfig(data)) console.log('Port:', data.port);串联多个守卫
对于复杂输入,请分层使用守卫:先检查 broad 结构,then 进一步细化。每个守卫都会再缩窄一些,逐步生成精确且安全的类型。
function process(v: unknown): string {
if (Array.isArray(v)) {
if (v.every((x) => typeof x === 'string')) {
return v.join('-');
}
}
return 'invalid';
}
console.log(process(['a', 'b']), process([1, 2]));对无效数据抛出异常
验证必需数据失败时,请抛出异常。结合返回never的失败辅助函数,可以保持正常路径简洁且类型明确。
function asNumber(v: unknown): number {
if (typeof v === 'number') return v;
throw new Error('Expected a number');
}
console.log(asNumber(42));
try { asNumber('x'); } catch (e) { console.log('rejected'); }整合运用
完整模式是:以unknown接收数据,使用守卫进行缩窄,然后操作精确的类型。这是无类型外部世界与带类型代码之间的安全边界。
type Point = { x: number; y: number };
function isPoint(v: unknown): v is Point {
return typeof v === 'object' && v !== null &&
'x' in v && 'y' in v;
}
const input: unknown = { x: 1, y: 2 };
if (isPoint(input)) console.log(input.x + input.y);快速检查
检验您对安全处理未知类型的理解。
回顾:处理未知类型
您已学会使用以下方式缩窄unknown:
- 使用
typeof处理原始类型,使用instanceof处理类实例。 - 使用
in运算符检查对象属性。 - 使用返回
value is T的自定义类型守卫。 - 在信任
JSON.parse的结果之前进行验证。
下一课程:类型断言与类型转换。
function isNonEmpty(v: unknown): v is string {
return typeof v === 'string' && v.length > 0;
}
console.log(isNonEmpty('hi'), isNonEmpty(''));常见问题解答
「类型安全地处理 unknown」课时是免费的吗?
是的 — 「类型安全地处理 unknown」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。
「类型安全地处理 unknown」这节课中我会学到什么?
先收窄 unknown 值,再安全地使用它们。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 TypeScript Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「类型安全地处理 unknown」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 TypeScript Academy 课中编写并运行代码吗?
能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 理解 unknown 与 any
- never 类型与不可能状态
- 函数中的 void 类型
- 类型安全地处理 unknown