如何在变量初始化/更新时强制执行TypeScript严格类型检查?
问题原因
TypeScript的类型断言(as Http[])只是编译阶段的类型提示,完全不涉及运行时校验。编译完成后所有类型信息会被擦除,YAML解析出来的原始对象(哪怕包含多余字段wazaa)会原封不动地被使用。TS不会帮你在运行时过滤多余属性、校验字段类型或必填性——类型断言本质是“你告诉TS这个值的类型,TS选择相信你”,而不是“TS帮你验证这个值符合类型”。
解决方案
要实现严格的类型检查,必须在运行时对YAML解析后的数据做校验,因为编译后的JS没有类型信息。下面是两种可行方案:
方案1:手写运行时校验函数
自己编写校验逻辑,逐个检查字段的存在性和类型,还可以按需禁止多余字段:
type Http = { name: string api: string resp: number status: string statusEffective: string } // 校验单个对象是否符合Http类型 function isHttp(obj: unknown): obj is Http { if (typeof obj !== 'object' || obj === null) return false; const httpObj = obj as Record<string, unknown>; // 检查必填字段的类型 const requiredFields: Array<[keyof Http, string]> = [ ['name', 'string'], ['api', 'string'], ['resp', 'number'], ['status', 'string'], ['statusEffective', 'string'], ]; for (const [field, type] of requiredFields) { if (!(field in httpObj) || typeof httpObj[field] !== type) { return false; } } // 严格禁止多余字段(可选,不需要可删除此段) if (Object.keys(httpObj).length !== requiredFields.length) { return false; } return true; } // 校验数组是否全为Http类型 function isHttpArray(arr: unknown): arr is Http[] { if (!Array.isArray(arr)) return false; return arr.every(item => isHttp(item)); } export const monitorHttp = () => { const rawConf = getConf("conf-http.yml"); if (!isHttpArray(rawConf)) { log.error("配置文件不符合Http数组格式"); process.exit(1); } const conf = rawConf; // 此时conf类型自动推导为Http[] log.info("", conf); }
方案2:使用第三方校验库(推荐)
用成熟的运行时类型校验库(如zod、io-ts),这类库能同时生成编译时类型和运行时校验逻辑,避免重复代码。以zod为例:
- 安装依赖:
npm install zod - 编写schema并校验:
import { z } from 'zod'; // 定义zod schema,同时生成对应的TypeScript类型 const HttpSchema = z.object({ name: z.string(), api: z.string(), resp: z.number(), status: z.string(), statusEffective: z.string(), }).strict(); // strict() 模式禁止多余字段,不需要可移除 // 从schema推导TS类型 type Http = z.infer<typeof HttpSchema>; // 定义数组schema const HttpArraySchema = z.array(HttpSchema); export const monitorHttp = () => { const rawConf = getConf("conf-http.yml"); // 校验数据,不符合则抛出错误(用safeParse可返回结果而非抛出) try { const conf = HttpArraySchema.parse(rawConf); log.info("", conf); } catch (err) { log.error("配置文件格式错误:", err); process.exit(1); } }
parse:数据不符合schema时抛出错误,适合直接终止流程的场景;safeParse:返回包含success字段的对象,不会抛出错误,适合自定义错误处理的场景。
内容的提问来源于stack exchange,提问作者WoJ
相关产品推荐
相关产品推荐

