为何TypeScript不接受if(Array.length)区分数组与对象?
为什么
if(a.length)无法将string[] | Object类型收窄为数组? TypeScript的类型收窄不是靠运行时的实际值逻辑推断,而是依赖明确的类型守卫规则,这就是问题的核心:
- 首先,
Object类型在TS里是个超级宽泛的类型,所有非原始类型(包括自定义对象、DOM元素甚至类实例)都属于它。哪怕普通对象也可以手动加length属性,比如{ length: 0 },这种对象能通过if(a.length)的检查,但它根本不是数组,自然没有map方法。 - 当你写
if(a.length)时,TS只会推断出a包含length属性,但无法确定这个属性来自数组——它可能来自任何带length的非数组对象。所以此时a的类型会被收窄为(string[] | Object) & { length: any },不是纯数组类型,调用map自然会报错。 - 而
Array.isArray(a)是TS内置的标准类型守卫函数,TS对它的行为有明确认知:只要这个函数返回true,参数就一定是数组类型,所以能精准把a的类型收窄为string[],调用map就没问题。 - 如果一定要用类似
length的判断逻辑,你可以自己写个自定义类型守卫:function isStringArray(a: string[] | Object): a is string[] { return Array.isArray(a) && typeof a.length === 'number'; } if (isStringArray(a)) { a.map(item => console.log(item)); // 无报错 }
内容的提问来源于stack exchange,提问作者Lord-JulianXLII
相关产品推荐
相关产品推荐

