如果TypeScript是JavaScript的严格超集,为什么任意对象上的点符号都是错误的?我有JS代码,我想转换到TS以获得更好的类型安全性,但所有使用点表示法的访问(例如,myObj.thing
)都给出了错误Property 'thing' does not exist on type '{}'.
。当我使用括号表示法(例如,myObj['thing']
)时,它可以正常工作。
答案 0 :(得分:8)
我知道你说这很奇怪,但这是TypeScript存在的主要原因之一。此错误有助于防止在对象上意外设置或获取不存在的属性。
现在,正如编译器告诉你的那样,bar
上的属性x
不存在,因为在编写{}
时它已隐式输入var x = {};
。< / p>
通过明确定义类型,可以告诉编译器x
具有多于零的属性:
var x: { foo?: string; bar?: string; } = {};
现在,您可以在没有编译器抱怨的情况下获取或设置x.foo
和x.bar
。在大多数情况下,您可以将其移动到如下界面:
interface IFooBar {
foo?: string;
bar?: string;
}
var x: IFooBar = {};
x.foo = "asdf"; // ok
x.test = "asdf"; // error, as it should be
有些人建议你施放any
,但不要偷懒。您应该充分利用TypeScript提供的类型系统。这样做绝对可以节省您在维护应用程序时的时间。
答案 1 :(得分:1)
由于Typescript对象的强类型特性,你可以使用&#34; any&#34;使它无类型:
var x: any = {};
x.bar = "bar"; /// ok
如果你需要的是定义文字属性的类型
var x: { [index: string]: TypeA } = {};
然后x["bar"]
现在只能是TypeA的实例。
答案 2 :(得分:0)
x
不包含任何名为bar
的属性,因此您需要在对象中创建它:
function foobar() {
var x = {
foo: 'foo',
bar: 'bar'
}
return x;
}
alert(foobar().bar); //returns bar
答案 3 :(得分:0)
在上面的代码中,Typescript无法确定对象x
是否公开了一个名为bar
的属性,因此在显示Intellisense时无法解析它。
相反,添加foo
,bar
等作为对象本身的属性:
var x = {
foo: "FOO",
bar: "BAR"
};
然后,当使用Typescript Playground时,您将看到Intellisense按预期工作:
HTH
答案 4 :(得分:0)
我个人更喜欢在有机会时指定类型。
请注意,如果您使用{}
运算符将字段定义为可选字段,则只能使用?:
实例化此变量。
let x: {foo?: string, bar?: string} = {};
x.foo = 'foo';
x.bar = 'bar';
正如其他人所说,如果你计划多次使用这种类型,最好为它做一个明确的类。
PS:在打字稿中编程时,最好使用let
代替var
。 (例如var
声明的范围有点古怪,而let
则与您期望它做的事情相同。)