跨函数边界细化联合类型
使用可辨识联合、谓词返回值和 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 反馈 — 无需本地设置。
此课程中的所有课时
- 穷尽式 switch 与 never 检查
- 谓词函数与 satisfies 运算符
- 跨函数边界细化联合类型