0Pricing
TypeScript Academy · 课时

类型安全地处理 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 理解 unknown 与 any
  2. never 类型与不可能状态
  3. 函数中的 void 类型
  4. 类型安全地处理 unknown
← 返回 TypeScript Academy