【问题标题】:Cannot deduce type of const after explicit type check? (TS2349: Cannot invoke an expression whose type lacks a call signature.)显式类型检查后无法推断出 const 的类型? (TS2349:无法调用类型缺少调用签名的表达式。)
【发布时间】:2018-12-03 23:58:38
【问题描述】:

我在使用 TypeScript 时遇到了一个奇怪的问题,似乎我应该能够推断出一个常量是一个数组,并且有了这个知识就可以调用数组方法。但是,即使经过显式检查,TypeScript 显然也无法确定一个值是否真的是一个数组。

给定:

type Maybe<T> = T | null | undefined;

type Value = string
  | number
  | string[]
  | number[]
  | Maybe<number | string>[];

如果我因此对常量进行类型检查,我可以在常量上调用 .every 数组方法:

// This approach works fine:
const currVal: Maybe<Value> = perhapsSomeValueSomewhere;

if (Array.isArray(currVal)) {
  const arr: any[] = currVal;
  const isListOfStrings = arr.every((s) => typeof(s) === 'string');

  // ... Do other stuff here
}

我觉得应该遵循以上可以简化为:

// This approach results in an error:
const currVal: Maybe<Value> = perhapsSomeValueSomewhere;
const isListOfStrings = Array.isArray(currVal)
  && currVal.every((s) => typeof(s) === 'string');

// ... Do other stuff here

但是这种方法会导致错误:

TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((callbackfn: (value: string, index: number, array: string[]) => boolean, thisArg?: any) => boole...' has no compatible call signatures.

我只能假设这意味着,在此过程中,TypeScript 已经失去了 &amp;&amp; currVal.every((s) =&gt; ... 时的上下文,currVal 确实是某种数组。

当这两位逻辑看起来相当可比时,为什么后者会导致错误?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    在第一种情况下,您通过将 currVal 分配给 any[] 来进行隐式类型转换,在第二种情况下,您没有将类型转换为数组类型。您可以使用以下显式强制转换来使用它。

    const isListOfStrings = Array.isArray(currVal) && (<Array<any>>currVal).every((s) => typeof (s) === 'string');
    

    【讨论】:

    • 感谢您的回复 - 将常量声明为 arr: any[] 和严格 casting 之间是否有区别,这就是我认为我们在您的示例中所做的: &lt;Array&lt;any&gt;&gt;currVal。我的印象是前者提供了一些编译时安全性,而后者则没有?
    • 我已经整理了答案中的术语,当您分配给 any[] 时,会发生隐式转换,如果已知分配无效,编译器会发出警告,当您这样做时显式转换如果无效,编译器也会发出警告。您的代码示例的潜在问题是不一定事先知道 Value 将具有什么类型,因此编译器不会发出警告。在您的示例的两个实例中,您在运行时都受到 Array.isArray 调用的保护,因为 && 运算符仅在 first 为真时计算第二个表达式。
    • 感谢您的解释!
    猜你喜欢
    • 2020-02-07
    • 2023-03-20
    • 2016-03-30
    • 2017-10-11
    • 2020-05-17
    • 1970-01-01
    • 2017-09-01
    • 2017-12-19
    • 2021-02-06
    相关资源
    最近更新 更多