spring的技术笔记
前端1 分钟阅读

TypeScript 类型收窄实战:从联合类型到 satisfies

用类型守卫、判别联合和 satisfies,把「运行时其实安全」变成编译器也认可的安全。

TypeScript 真正省时间的地方,往往不是把类型写得更花,而是在分支里让类型跟着数据变窄。收窄做好了,as 会明显变少。

判别联合

给对象加一个字面量字段,比一堆 optional 字段好维护:

type Result =
  | { ok: true; data: string }
  | { ok: false; error: string };
 
function render(result: Result) {
  if (result.ok) {
    return result.data; // data 可用
  }
  return result.error; // error 可用
}

自定义类型守卫

当第三方数据或 unknown 进门时:

function isPost(value: unknown): value is { title: string; slug: string } {
  if (!value || typeof value !== "object") return false;
  const v = value as Record<string, unknown>;
  return typeof v.title === "string" && typeof v.slug === "string";
}

守卫返回 true 后,后续分支里类型会被收窄——这比盲目 as Post 更诚实。

satisfies:约束形状又保留字面量

satisfies 适合配置对象:既要符合接口,又不想被放宽成宽类型。

const categories = {
  frontend: "前端",
  backend: "后端",
  ai: "AI 学习",
} as const satisfies Record<string, string>;
 
// categories.frontend 仍是 "前端" 字面量

实践建议

  • API 边界用 unknown + 守卫/校验库,不要信任 any。
  • 组件 props 优先用判别联合表达互斥 UI 状态。
  • 忍不住写 as 时,先问能不能用收窄或提前校验替代。

小结

类型收窄是把运行时已经做的判断,同步告诉编译器。养成这个习惯后,重构会安全很多。