简体   繁体   English

对对象的TypeScript和点符号访问

[英]TypeScript and dot-notation access to objects

If TypeScript is a strict superset of JavaScript, why is dot notation on an arbitrary object erroneous? 如果TypeScript是JavaScript的严格超集,那么为什么任意对象上的点符号错误? I have JS code that I want to convert over to TS for better type safety, but all access using dot notation (eg, myObj.thing ) gives me the error Property 'thing' does not exist on type '{}'. 我有一些JS代码,我想将它们转换为TS,以获得更好的类型安全性,但是所有使用点表示法(例如myObj.thing )的访问都给我以下错误: Property 'thing' does not exist on type '{}'. . It works properly when I use bracket notation (eg, myObj['thing'] ). 当我使用方括号表示法(例如, myObj['thing'] )时,它可以正常工作。

类型不存在该属性

I know you say this is odd, but this is one of the main reasons TypeScript exists. 我知道您说这很奇怪,但这是TypeScript存在的主要原因之一。 This error helps prevent accidentally setting or getting non-existent properties on an object. 此错误有助于防止意外设置或获取对象上不存在的属性。

Right now, as the compiler is telling you, the property bar does not exist on x because it has been implicitly typed to {} when writing var x = {}; 眼下,因为编译器告诉你,属性bar不上不存在x ,因为它已被隐式类型,以{}书写时var x = {}; .

You can tell the compiler that x has more than zero properties by explicitly defining the type: 通过显式定义类型,可以告诉编译器x具有不止零个属性:

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

Now you can get or set x.foo and x.bar without the compiler complaining. 现在,您可以获取或设置x.foox.bar而无需编译器抱怨。 In most cases, you would move this into an interface like so: 在大多数情况下,您可以将其移动到如下所示的界面中:

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

var x: IFooBar = {};

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

Some people are recommending you cast to any , but don't get lazy. 有人建议您选择any ,但不要偷懒。 You should make full use of the type system TypeScript provides. 您应该充分利用TypeScript提供的类型系统。 Doing so will most definitely save you time down the road as you maintain an application. 这样做绝对可以在您维护应用程序时节省您的时间。

Because of the strongly-typed nature of Typescript Object, you can use "any" to make it untyped: 由于Typescript对象具有强类型化的性质,因此可以使用“ any”使其变为非类型化:

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

If what's you need is to define type of literal properties 如果您需要定义文字属性的类型

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

then x["bar"] can now only be instance of TypeA. 那么x["bar"]现在只能是TypeA的实例。

x does not hold any property named bar so you need create it within the object: x不包含任何名为bar属性,因此您需要在对象中创建它:

function foobar() {
    var x = {

        foo: 'foo',
        bar: 'bar'
    }

    return x;
}

alert(foobar().bar); //returns bar

mwilson got there before I could! 麦威尔逊在我无法到达之前就到达了那里! ;) ;)

In the code above, Typescript is unable to determine that the object x exposes a property called bar so cannot resolve it when displaying Intellisense. 在上面的代码中,Typescript无法确定对象x公开了名为bar的属性,因此在显示Intellisense时无法解析它。

Instead, add foo , bar , etc. as properties of the object itself: 而是将foobar等添加为对象本身的属性:

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

Then, when using the Typescript Playground , you'll be see the Intellisense work as expected: 然后,在使用Typescript Playground时 ,您将看到Intellisense的工作按预期进行:

在此处输入图片说明

HTH 高温超导

I personally prefer to specify types whenever I have the chance. 我个人更愿意在有机会时指定类型。

Note, that you can only instantiate this variable with {} if you define the fields as optional with the ?: operator. 请注意,如果您使用?:运算符将字段定义为可选字段,则只能使用{}实例化此变量。

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

As others have said, if you plan to use this type multiple times, it's probably better to make an explicit class for it. 正如其他人所说,如果您打算多次使用此类型,最好为它创建一个显式类。

PS: it's better to use let instead of var when programming in typescript. PS:在打字稿中编程时,最好用let代替var (eg the scope of a var declaration is a bit quirky, compared to a let which does what you expect it to do.) (例如,与一个let相比, var声明的范围有点古怪。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM