TypeScript如何不使用any实现支持任意属性的对象非空校验
问题解决方案
你原有代码类型报错的核心原因是自定义索引签名将属性值限定为number | string,无法兼容数组、布尔值等其他类型的属性,不需要使用any就能解决问题,推荐两种类型安全的实现方式:
方式1:使用内置Record工具类型(最简洁)
直接用TS内置的Record类型定义入参,值类型设为unknown即可接收任意类型的属性值,同时保留类型安全性(比any更严谨,不会绕过TS类型校验),同时补全你没写完的判断逻辑:
export const objectIsEmpty = (a: Record<string, unknown>) => { // 先判断入参是否为真值,再判断自有属性数量是否为0 return !!a && Object.keys(a).length === 0; }
这个写法可以完全覆盖你所有的调用示例:
objectIsEmpty({})正确返回trueobjectIsEmpty({ jamie: 'hutber' })正确返回falseobjectIsEmpty({fank: 'skinner', jamie: 'hutber' })正确返回falseobjectIsEmpty({anArray: [], aBoolie: false, chickenSkin: 'isGreat'})数组、布尔值、字符串都属于unknown的子类型,不会报类型错误,正确返回false
方式2:修改原有自定义接口的索引签名
如果你想保留自定义接口的写法,只需要把索引签名的值类型从number | string改成unknown即可:
interface ObjectIsEmptyProps { [index: string]: unknown; } export const objectIsEmpty = (a: ObjectIsEmptyProps) => { return !!a && Object.keys(a).length === 0; }
注意事项
不要用TS内置的object类型作为入参类型,object类型仅表示值是非原始值的对象,但不支持索引访问,也无法兼容键值对结构的类型推导,不适合这个场景。unknown相比any的优势是不会关闭类型检查,如果你后续要操作对象内的属性,TS会要求你先做类型收窄,避免隐式类型错误。
内容的提问来源于stack exchange,提问作者Jamie Hutber
相关产品推荐
相关产品推荐

