0Pricing
TypeScript Academy · 课时

跨函数边界细化联合类型

使用可辨识联合、谓词返回值和 Result 风格的类型,将安全的类型收窄跨越函数边界传递下去。

跨函数边界细化联合类型 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 3 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 3 节课。

简介

目标:通过标签联合类型、谓词返回值和验证辅助函数,让类型收窄在函数调用之间保持有效。

  • 调用位置无需不安全的 as
  • 细化后的类型随数据传递

标签联合类型返回值

Result 模式:调用者通过检查 ok 来收窄类型。无需类型转换,控制流也很清晰。

type Ok<T> = { ok: true; value: T }
type Err = { ok: false; error: string }

type Result<T> = Ok<T> | Err

function parseIntSafe(s: string): Result<number> {
  const n = Number(s)
  return Number.isFinite(n) ? { ok: true, value: n } : { ok: false, error: "NaN" }
}

function useIt(s: string) {
  const r = parseIntSafe(s)
  if (r.ok) {
    // r is Ok<number>
    return r.value * 2
  }
  // r is Err
  return `bad: ${r.error}`
}

谓词返回值

谓词返回值(x is T)会集中处理检查,并让细化后的类型保留在调用位置。

type User = { id: number; name: string }

type MaybeUser = User | null

function hasUser(x: MaybeUser): x is User {
  return x !== null
}

function greet(x: MaybeUser) {
  if (hasUser(x)) {
    // x narrowed to User
    return `Hello ${x.name}`
  }
  return "Anonymous"
}

传递类型细化

使用守卫(例如 isCircle)进行细化,然后继续传递该值;下游函数会看到更窄的类型。

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; size: number }

function isCircle(s: Shape): s is Extract<Shape, { kind: "circle" }> {
  return s.kind === "circle"
}

function area(s: Shape) {
  if (isCircle(s)) {
    // s is circle here
    return Math.PI * s.radius * s.radius
  }
  return s.size * s.size
}

在边界处验证

在边界处进行验证并返回 Valid/Invalid;调用者根据标签收窄类型,并获得完整类型化的数据。

type Payload = { email: string; retries?: number }

type Valid = { ok: true; data: Required<Payload> }
type Invalid = { ok: false; issues: string[] }

type Validation = Valid | Invalid

function validate(p: unknown): Validation {
  const issues: string[] = []
  if (typeof p !== "object" || p === null) return { ok: false, issues: ["not an object"] }
  const x = p as any
  if (typeof x.email !== "string") issues.push("email:string")
  if (x.retries !== undefined && typeof x.retries !== "number") issues.push("retries:number")
  if (issues.length) return { ok: false, issues }
  return { ok: true, data: { email: x.email, retries: x.retries ?? 0 } }
}

function handle(p: unknown) {
  const v = validate(p)
  if (!v.ok) return `bad: ${v.issues.join(",")}`
  // v.data is fully typed here
  return `send to ${v.data.email} (${v.data.retries})`
}

提示

最佳实践:

  • 优先使用简短且稳定的标签(ok、kind)
  • 将检查集中在谓词辅助函数中
  • 在调用位置使用穷尽式分支
  • 避免使用 any 和不安全的类型转换

跨边界类型收窄

快速检查:哪种模式最能在函数边界之间保留类型收窄?

回顾

回顾:将类型细化作为数据(Result)传递,在边界处进行验证,并避免不安全的类型转换;调用者通过简单的标签检查来收窄类型。

常见问题解答

「跨函数边界细化联合类型」课时是免费的吗?

是的 — 「跨函数边界细化联合类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 3 节课。

「跨函数边界细化联合类型」这节课中我会学到什么?

使用可辨识联合、谓词返回值和 Result 风格的类型,将安全的类型收窄跨越函数边界传递下去。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 TypeScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 3 节。

「跨函数边界细化联合类型」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 TypeScript Academy 课中编写并运行代码吗?

能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 穷尽式 switch 与 never 检查
  2. 谓词函数与 satisfies 运算符
  3. 跨函数边界细化联合类型
← 返回 TypeScript Academy