【问题标题】:Why does accessing a property of indexOf still compile?为什么访问 indexOf 的属性仍然可以编译?
【发布时间】:2019-06-12 17:50:27
【问题描述】:

我在 TypeScript 中犯了一个错字,这是在代码审查期间发现的。

我使用了someArray.indexOf[someObject] 而不是someArray.indexOf(someObject)

我预计 IDE/编译器会出错。相反,没有引发错误,结果只是未定义。

谁能解释一下?

【问题讨论】:

  • 你分配的结果是什么?因为您写的是有效,所以您正在使用indexOf 方法的someObject 成员。嗯,正在努力。唯一的错误来自 TypeScript 编译,并且仅当您尝试将结果分配给与预期类型不匹配的内容时。
  • 欢迎使用javascript,一切都是对象!
  • @DeWetvanAs 我其实对你的问题很好奇 - 这似乎是 TypeScript see example here 的真正错误/问题。似乎如果您尝试分配给number 类型的变量,.indexOf[someObject] 的结果 不应 被视为number,因此编译将失败。这就是 TypeScript 的全部思想 - 强制执行类型。这里的答案集中在 JS 上,但忽略了这一点。
  • @vlaz 实际上是一个具有多个属性的复杂对象。

标签: typescript methods properties


【解决方案1】:

这里唯一真正的问题是您希望 Typescript 抛出一个错误,从而暴露您的逻辑问题。预期的逻辑是使用花括号并利用someArray.indexOf(someObject) 函数。

当您使用方括号someArray.indexOf[someObject] 时发生的情况是,JS 运行时首先通过调用函数someObject.toString 将您的对象someObject 转换为字符串,该函数很可能返回"[object object]"。然后在someArray.indexOf 对象中查询不存在的键"[object object]",返回undefined。就 Typescript 而言,这完全没问题。

David Sherret 指出 --noImplicitAny 会指出错误,但正如他解释的那样,它只会指出不同的错误,这不会直接帮助您找到逻辑中的缺陷。

【讨论】:

  • "就 Typescript 而言,这完全没问题。" 不,不是。这个表达式的结果是不确定的,TypeScript 会识别它并且应该报告一个错误,因为返回的 type 将是 any 而不是 number。这对于 TypeScript 来说是好的 - 请记住,它的存在是为了确保类型安全。说“哦,你想要一件事没关系,但你不能保证得到它”——这与 TS 的核心意图相反。
【解决方案2】:

它不会出错,因为 --noImplicitAny compiler option 未启用。启用该编译器选项后,您将收到预期的错误:

原因是元素访问表达式返回一个类型为any 的对象,而该类型没有定义index signature(这是一个隐含的any)。

同样,由于--noImplicitAny 未启用,它不会出错。我强烈建议打开这个编译器选项。

【讨论】:

    【解决方案3】:

    很简单。

    someArray.indexOf你知道这是一个function,它也是一个对象,可以有属性。

    通过执行someArray.indexOf[someObject],您正在尝试使用值为someObject 的值的键访问属性。

    当然,indexOf函数上没有定义,所以返回undefined

    说明语法和函数可以具有属性的事实的快速示例;):

    const array = [];
    array.indexOf['anyValue'] = 'test';
    console.log(array.indexOf.anyValue);

    编辑

    这是对 TypeScript 问题的尝试。

    如您所知,TypeScript 旨在与 JavaScript 兼容。因此,就像在 JS 中一样,您可以通过以下方式访问对象的属性:

    • '静态':obj.property
    • “动态”:obj['property']

    通过使用“静态”方式访问属性,TypeScript 当然会报错!

    但是使用动态访问属性的方式,TypeScript 编译器无法确定它的类型或它是否存在,因为括号之间的值将在运行时在 TypeScript 转译之后进行评估。

    这就是为什么它会被隐式标记为any

    正如 David Sherret 在他的 answer 中提到的,您可以通过添加标志 --noImplicitAny 来强制 TypeScript 引发错误,有关此问题的更多详细信息,请参阅他的回答!

    希望这会有所帮助;)

    【讨论】:

    • 我认为这里的答案缺少TypeScript 标签。预计 TS 中会出现编译错误是完全合理的。再说一次,这取决于你是否有index: numberindex = arr.indexOf[obj] 那么这应该是一个编译错误。但是index: any 不会抛出编译错误。
    • @vlaz +1。 sjahan 快速解释了undefined 结果,但主要问题仍然存在......
    • "当然,有人会说编译器可以理解" 是的,编译器会理解。这就是编译器存在的全部原因,如果 TypeScript 无法确定类型未确定,那么 TS 到底有什么好处?这只是对语句的逻辑检查 - David Sherret's answer 指出 TS 确实理解未确定的类型并且可能会引发错误。因此,您的编辑分配了不正确的假设和信息。
    • @vlaz 我认为我没有正确表达自己,我的观点可能会被误解。我要编辑最后一部分,谢谢。
    【解决方案4】:

    array.indexOf 是一个函数。

    函数就是对象。

    您正在访问array.indexOf 函数的someObject 属性。

    你会得到undefined

    const array = [1, 2, 3]
    const someObject = 'asdasd'
    
    console.log(array.indexOf[someObject])
    // undefined

    【讨论】:

    • Array.indexOfundefined,另一方面,Array.prototype.indexOf 是一个函数。
    • 你是对的!我修正了答案中的错字。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多