如何在嵌套TypeScript类型谓词函数中避免使用as any?
你的思路完全没问题——复用基础类型的校验函数来避免重复代码,是很合理的可维护性实践。要去掉讨厌的as any,可以试试这两种方案:
方案一:用in操作符+unknown参数强化类型安全
把谓词函数的参数类型从any换成unknown(更符合TypeScript的严格类型理念),然后通过in操作符先确认属性存在,再做类型检查:
type SerializableA = { one: string } type SerializableB = SerializableA & { two: number } type SerializableC = SerializableA & { three: string | null } function isSerializableA(thing: unknown): thing is SerializableA { if(typeof thing !== "object" || thing === null) return false; const obj = thing as Record<string, unknown>; if(typeof obj["one"] !== "string") return false; return true; } function isSerializableB(thing: unknown): thing is SerializableB { if(!isSerializableA(thing)) return false; // 用in操作符告诉TypeScript:这个对象可能有two属性 if(!("two" in thing) || typeof thing["two"] !== "number") return false; return true; } function isSerializableC(thing: unknown): thing is SerializableC { if(!isSerializableA(thing)) return false; if(!("three" in thing)) return false; const threeProp = thing["three"]; if(threeProp !== null && typeof threeProp !== "string") return false; return true; }
方案二:用精确类型断言替代as any
如果不想改参数类型,也可以在通过isSerializableA校验后,把对象断言为SerializableA & Record<string, unknown>——这种断言既保留了基础类型的校验结果,又允许我们访问任意属性,比as any安全得多:
function isSerializableB(thing: any): thing is SerializableB { if(!isSerializableA(thing)) return false; const serializable = thing as SerializableA & Record<string, unknown>; if(typeof serializable["two"] !== "number") return false; return true; }
要不要用as any?
别用。as any确实能快速消除报错,但它会完全绕过TypeScript的类型检查,万一你把two写成tow这类拼写错误,TypeScript根本帮不了你。这种场景下有明确的安全替代方案,没必要冒这个风险。
内容的提问来源于stack exchange,提问作者BooleanAssange
相关产品推荐
相关产品推荐

