Javascript 对对象的类型脚本和点符号访问
如果TypeScript是JavaScript的严格超集,为什么任意对象上的点表示法是错误的?为了更好的类型安全性,我想将JS代码转换为TS,但是所有使用点表示法的访问(例如,Javascript 对对象的类型脚本和点符号访问,javascript,typescript,Javascript,Typescript,如果TypeScript是JavaScript的严格超集,为什么任意对象上的点表示法是错误的?为了更好的类型安全性,我想将JS代码转换为TS,但是所有使用点表示法的访问(例如,myObj.thing)都会给我一个错误,属性“thing”在类型“{}”上不存在。。当我使用括号表示法(例如,myObj['thing'])时,它可以正常工作 x不包含任何名为bar的属性,因此需要在对象中创建它: function foobar() { var x = { foo: 'foo'
myObj.thing
)都会给我一个错误,属性“thing”在类型“{}”上不存在。
。当我使用括号表示法(例如,myObj['thing']
)时,它可以正常工作
x
不包含任何名为bar
的属性,因此需要在对象中创建它:
function foobar() {
var x = {
foo: 'foo',
bar: 'bar'
}
return x;
}
alert(foobar().bar); //returns bar
mwilson比我早到了那里!;) 在上面的代码中,Typescript无法确定对象
x
是否公开名为bar
的属性,因此在显示Intellisense时无法解析该属性
相反,添加foo
、bar
等作为对象本身的属性:
var x = {
foo: "FOO",
bar: "BAR"
};
然后,在使用时,您将看到Intellisense按预期工作:
HTH我知道你说这很奇怪,但这是TypeScript存在的主要原因之一。此错误有助于防止意外设置或获取对象上不存在的属性 现在,正如编译器告诉您的那样,
bar
属性在x
上不存在,因为它在编写var x={}时被隐式键入到{}
代码>
通过显式定义类型,可以告诉编译器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提供的类型。这样做肯定会节省您维护应用程序的时间。由于Typescript对象的强类型特性,您可以使用“any”将其取消类型化:
var x: any = {};
x.bar = "bar"; /// ok
如果您需要的是定义文本属性的类型
var x: { [index: string]: TypeA } = {};
然后x[“bar”]
现在只能是TypeA的实例。我个人更喜欢在有机会的时候指定类型
请注意,如果使用?:
运算符将字段定义为可选字段,则只能使用{}
实例化此变量
let x: {foo?: string, bar?: string} = {};
x.foo = 'foo';
x.bar = 'bar';
正如其他人所说,如果您计划多次使用此类型,那么最好为其创建一个显式类
PS:在使用typescript编程时,最好使用let
而不是var
。(例如,var
声明的范围与let
声明相比有点古怪。)这是一个警告,它仍然应该编译,因此TypeScript仍然是JS的严格超集。它警告您的原因是键入了TypeScript,并且x
的类型没有指定bar
属性。您可以强制转换到任何
,应用具有条的接口,或使用[“bar”]
@Asad:显示和描述的错误被报告为正确的错误,而不是警告,并且我的构建失败。但是,我能够成功地转换到任何。TypeScript故意比JavaScript严格,因此在JavaScript中合法并不一定意味着TypeScript编译器会同意。它是分配给对象中尚不存在的属性,所以在TS中,如果没有对any
(如上@Asad所述)的转换,我就无法做到这一点,这似乎很奇怪。。。我想有多种不同的方法给猫剥皮。