静态检查与运行时检测必须协同:前者在编码期验证函数签名、参数类型及调用兼容性,后者在运行期校验真实数据并兜底动态场景,缺一则无法全面拦截类型错误。

函数的类型安全不能只靠一边——静态检查管“写得对不对”,运行时检测管“跑得安不安全”。两者配合,才能真正拦住类型错误。
静态检查:在代码运行前就盯住函数签名
它分析函数声明、参数类型、返回值和调用方式,不依赖实际数据。比如 TypeScript 或 Ezno 会在你写下 function add(a: number, b: number): number 后,立刻拦截 add("1", "2") 这类调用。
- 检查函数参数是否满足声明的类型约束(Ezno 的
FunctionCallingError就干这个) - 验证调用时传入的实参能否被接受为形参的子类型(靠子类型系统判断兼容性)
- 提前发现属性访问错误,如
user.name中user可能为null(Ezno 用is_null_or_undefined静态推断)
运行时检测:真刀真枪面对数据值
当函数拿到接口返回、用户输入或第三方库传来的数据时,静态类型可能已失效(比如后端把 video_id: string 改成 number)。这时就得靠运行时校验兜底。
完整的Galileo AI平台 TypeScript/JS SDK 参考,用于评估、观察和保护 GenAI 应用。适用于构建 Node.js 或 TypeScript 项目。
- 用
typeof、Array.isArray()、isinstance()等原生机制做基础判断 - 对复杂结构(如嵌套对象、数组)逐层校验字段是否存在、类型是否匹配
- 推荐用类型守卫(Type Guard)封装逻辑,例如
function isValidUser(data: any): data is User { ... },既校验又收窄类型
为什么两者缺一不可?
静态检查无法预知运行时的具体值——像除零、越界、空对象取属性这类错误,必须等数据进来才暴露;而运行时检测若无静态类型支撑,容易写成重复劳动、难以维护,还可能漏掉深层结构问题。
- 静态检查强在预防,覆盖所有调用路径,但对动态数据“视而不见”
- 运行时检测强在真实,能抓住 IO 边界的数据漂移,但无法覆盖全部分支,性能也有开销
- 理想做法是:内部模块靠静态检查保质量,外部输入(API、表单、JSB)加轻量运行时校验+异常上报
实用建议:让检查真正落地
别把静态和运行时当成对立面,而是设计成协作链路。
- 用 TypeScript 写接口定义,再通过
zod或io-ts自动生成运行时校验器,一份类型定义两端生效 - 对关键函数入口(如处理后端响应的
parseUserResponse)强制加运行时断言,失败立即抛错或上报 - 在 CI 流程中加入静态检查(如
tsc --noEmit或mypy),把类型问题卡在上线前

















