【问题标题】:TypeScript and dot-notation access to objectsTypeScript 和点符号访问对象
【发布时间】:2015-05-07 00:22:43
【问题描述】:

如果 TypeScript 是 JavaScript 的严格超集,为什么任意对象上的点符号是错误的?我有 JS 代码,我想将其转换为 TS 以获得更好的类型安全性,但所有使用点表示法(例如,myObj.thing)的访问都会给我错误Property 'thing' does not exist on type '{}'.。当我使用括号表示法(例如,myObj['thing'])时,它可以正常工作。

【问题讨论】:

  • 这是一个警告,它仍然应该编译,所以 TypeScript 仍然是 JS 的严格超集。它警告您的原因是因为 TypeScript 是类型化的,并且 x 的类型没有指定 bar 属性。您可以转换为any,应用具有bar 的接口,或使用["bar"]
  • @Asad:显示和描述的错误被报告为正确的错误,而不是警告,并且我的构建失败。但是,我可以成功转换为any
  • TypeScript 故意比 JavaScript 更严格,所以它在 J​​avascript 中合法并不一定意味着 TypeScript 编译器会同意。

标签: javascript typescript


【解决方案1】:

我知道你说这很奇怪,但这是 TypeScript 存在的主要原因之一。此错误有助于防止意外设置或获取对象上不存在的属性。

现在,正如编译器告诉您的那样,bar 属性在 x 上不存在,因为在编写 var x = {}; 时它已被隐式键入到 {}

您可以通过显式定义类型告诉编译器x 具有多个属性:

var x: { foo?: string; bar?: string; } = {};

现在您可以获取或设置x.foox.bar 而不会引起编译器的抱怨。在大多数情况下,您会将其移至如下界面:

interface IFooBar {
    foo?: string;
    bar?: string;
}

var x: IFooBar = {};

x.foo = "asdf";  // ok
x.test = "asdf"; // error, as it should be

有些人建议您投到any,但不要偷懒。你应该充分利用 TypeScript 提供的类型系统。这样做肯定会在您维护应用程序时节省您的时间。

【讨论】:

    【解决方案2】:

    由于 Typescript Object 的强类型特性,您可以使用“any”使其无类型:

    var x: any = {};
    x.bar = "bar";   /// ok
    

    如果您需要定义文字属性的类型

    var x: { [index: string]: TypeA } = {};
    

    那么x["bar"] 现在只能是 TypeA 的实例。

    【讨论】:

      【解决方案3】:

      x 不包含任何名为 bar 的属性,因此您需要在对象中创建它:

      function foobar() {
          var x = {
      
              foo: 'foo',
              bar: 'bar'
          }
      
          return x;
      }
      
      alert(foobar().bar); //returns bar
      

      【讨论】:

      • 这是apparently legal JS 分配给对象中尚不存在的属性,所以如果没有强制转换为any(如@ Asad 如上所述)。
      • 每天都在学习新东西...我猜有多种不同的给猫剥皮的方法。
      【解决方案4】:

      mwilson 在我之前到达那里! ;)

      在上面的代码中,Typescript 无法确定对象 x 暴露了一个名为 bar 的属性,因此在显示 Intellisense 时无法解析它。

      改为添加foobar等作为对象本身的属性:

      var x = {
          foo: "FOO",
          bar: "BAR"
      };
      

      然后,当使用Typescript Playground 时,您将看到 Intellisense 正常工作:

      HTH

      【讨论】:

        【解决方案5】:

        我个人更喜欢在有机会时指定类型。

        请注意,如果使用 ?: 运算符将字段定义为可选字段,则只能使用 {} 实例化此变量。

        let x: {foo?: string, bar?: string} = {};
        x.foo = 'foo';
        x.bar = 'bar';
        

        正如其他人所说,如果您打算多次使用此类型,最好为其创建一个显式类。

        PS:在打字稿中编程时最好使用let 而不是var。 (例如,var 声明的范围有点古怪,与 let 相比,它会按照您的预期进行。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-31
          • 1970-01-01
          • 2018-01-08
          • 2011-12-24
          相关资源
          最近更新 更多