元素隐式具有 'any' 类型,因为 'string' 类型的表达式不能用于索引类型 - Phaser
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type - Phaser
我知道有人问过这个问题,但仍然无法找到适合我的情况的解决方案。
我有一个文件,我在其中定义了某些值,然后我要遍历它们。我在这部分代码中收到错误
preloadImages(){
this.load.setPath("./assets/images");
for (const key in STATIC.IMAGES) {
if (STATIC.IMAGES.hasOwnProperty(key)) {
this.load.image(STATIC.IMAGES[key], STATIC.IMAGES[key]);
}
}
}
投诉来自 STATIC.IMAGES[key] 电话。
STATIC 来自
的文件
export const STATIC = {
SCENES: {
LOAD: "LOAD",
MENU: "MENU"
},
IMAGES: {
MENU_BG :"bg.png",
MENU_TITLE: "title.png",
MENU_PLAY: "play.png",
MENU_SETTINGS: "settings.png",
MENU_CREDITS: "credits.png",
MENU_SPEAKER: "speaker.png",
MENU_SPEAKER_MUTE: "speaker_mute.png"
},
SPRITES: {
LOOP: {
name: "loop.png",
size: 64
}
},
AUDIOS: {
BG_MUSIC: "airtone.mp3",
POP: "pop.mp3",
WOOSH: "woosh.mp3"
}};
不确定我是否理解为什么会发生这种情况以及如何解决它。
让我们将其缩减为 minimal, reproducible example。请随意将下面的 obj
替换为您的 STATIC.IMAGES
;这两种解释都是一样的:
let obj = { a: "hey", b: "you", c: "guys" };
for (const k in obj) {
console.log(obj[k].toUpperCase()); // error!
/* Element implicitly has an 'any' type because expression of type
'string' can't be used to index type '{ a: string; b: string; c: string; }'. */
}
这里我们有一个具有三个键的对象 obj
。我们尝试使用 for..in
循环迭代这些键,但我们得到一个错误,您不能使用 k
索引到 obj
。为什么?这不是 for..in
循环的意义吗?
这里的问题是 TypeScript 中的对象类型是 open 或 extendible,而不是 closed 或 精确 。您可以在不违反其类型的情况下向 TypeScript 中的对象添加额外的属性。这在某些情况下很棒:它允许您通过添加属性来扩展接口和子类 类。但在其他情况下,这很痛苦:
编译器将 obj
视为 {a: string, b: string, c: string}
类型的值。由于此类型不精确,当您执行 for (const k in obj)
时,编译器知道 k
将采用值 "a"
、"b"
和 "c"
,但它 不知道这些是唯一可能的值:
let hmm = { a: "hey", b: "you", c: "guys", d: 12345 };
obj = hmm; // no error!
obj = hmm
中没有错误,因为值 hmm
匹配 {a: string, b: string, c: string}
。 d
属性 不违反类型。因此,就编译器所知,for (const k in obj)
将枚举 "a"
、"b"
、"c"
和 谁知道其他 string
值。因此,k
的类型不是keyof typeof obj
。就是string
。
并且使用 string
类型的键索引到 {a: string, b: string, c: string}
是不安全的。实际上,将 hmm
分配给 obj
,调用 (12345).toUpperCase()
时会出现运行时错误。所以编译器警告你是正确的,即使不是很有用。
参见 microsoft/TypeScript#35847 for an "official" version of the answer to this question. Also see ,这是同一个问题,除了使用 Object.keys(obj).forEach(k => ...)
而不是 for (const k in obj) {...}
... 并且答案相同。
如果引入了确切的类型,那么这个问题也许就会消失。有一个功能请求:microsoft/TypeScript#12936。但看起来这不会很快发生。
现在,那么,能做些什么呢?好吧,如果我们确定 obj
不会有任何编译器不知道的额外键,我们就可以将其视为一个确切的类型,只是告诉编译器不要担心它.此 "telling the compiler" 采用 type assertion 的形式:
for (const k in obj) {
console.log(obj[k as keyof typeof obj].toUpperCase()); // okay
}
这里,k as keyof typeof obj
是类型断言。我们必须小心不要这样欺骗编译器,但只要我们小心,那就没问题。
为了完整性,您还可以在循环外声明 k
并为其指定一个更窄的类型;这相当于类型安全方面的类型断言:
let k: keyof typeof obj;
for (k in obj) {
console.log(obj[k as keyof typeof obj].toUpperCase()); // okay
}
好的,希望对您有所帮助;祝你好运!
我知道有人问过这个问题,但仍然无法找到适合我的情况的解决方案。
我有一个文件,我在其中定义了某些值,然后我要遍历它们。我在这部分代码中收到错误
preloadImages(){
this.load.setPath("./assets/images");
for (const key in STATIC.IMAGES) {
if (STATIC.IMAGES.hasOwnProperty(key)) {
this.load.image(STATIC.IMAGES[key], STATIC.IMAGES[key]);
}
}
}
投诉来自 STATIC.IMAGES[key] 电话。 STATIC 来自
的文件export const STATIC = {
SCENES: {
LOAD: "LOAD",
MENU: "MENU"
},
IMAGES: {
MENU_BG :"bg.png",
MENU_TITLE: "title.png",
MENU_PLAY: "play.png",
MENU_SETTINGS: "settings.png",
MENU_CREDITS: "credits.png",
MENU_SPEAKER: "speaker.png",
MENU_SPEAKER_MUTE: "speaker_mute.png"
},
SPRITES: {
LOOP: {
name: "loop.png",
size: 64
}
},
AUDIOS: {
BG_MUSIC: "airtone.mp3",
POP: "pop.mp3",
WOOSH: "woosh.mp3"
}};
不确定我是否理解为什么会发生这种情况以及如何解决它。
让我们将其缩减为 minimal, reproducible example。请随意将下面的 obj
替换为您的 STATIC.IMAGES
;这两种解释都是一样的:
let obj = { a: "hey", b: "you", c: "guys" };
for (const k in obj) {
console.log(obj[k].toUpperCase()); // error!
/* Element implicitly has an 'any' type because expression of type
'string' can't be used to index type '{ a: string; b: string; c: string; }'. */
}
这里我们有一个具有三个键的对象 obj
。我们尝试使用 for..in
循环迭代这些键,但我们得到一个错误,您不能使用 k
索引到 obj
。为什么?这不是 for..in
循环的意义吗?
这里的问题是 TypeScript 中的对象类型是 open 或 extendible,而不是 closed 或 精确 。您可以在不违反其类型的情况下向 TypeScript 中的对象添加额外的属性。这在某些情况下很棒:它允许您通过添加属性来扩展接口和子类 类。但在其他情况下,这很痛苦:
编译器将 obj
视为 {a: string, b: string, c: string}
类型的值。由于此类型不精确,当您执行 for (const k in obj)
时,编译器知道 k
将采用值 "a"
、"b"
和 "c"
,但它 不知道这些是唯一可能的值:
let hmm = { a: "hey", b: "you", c: "guys", d: 12345 };
obj = hmm; // no error!
obj = hmm
中没有错误,因为值 hmm
匹配 {a: string, b: string, c: string}
。 d
属性 不违反类型。因此,就编译器所知,for (const k in obj)
将枚举 "a"
、"b"
、"c"
和 谁知道其他 string
值。因此,k
的类型不是keyof typeof obj
。就是string
。
并且使用 string
类型的键索引到 {a: string, b: string, c: string}
是不安全的。实际上,将 hmm
分配给 obj
,调用 (12345).toUpperCase()
时会出现运行时错误。所以编译器警告你是正确的,即使不是很有用。
参见 microsoft/TypeScript#35847 for an "official" version of the answer to this question. Also see Object.keys(obj).forEach(k => ...)
而不是 for (const k in obj) {...}
... 并且答案相同。
如果引入了确切的类型,那么这个问题也许就会消失。有一个功能请求:microsoft/TypeScript#12936。但看起来这不会很快发生。
现在,那么,能做些什么呢?好吧,如果我们确定 obj
不会有任何编译器不知道的额外键,我们就可以将其视为一个确切的类型,只是告诉编译器不要担心它.此 "telling the compiler" 采用 type assertion 的形式:
for (const k in obj) {
console.log(obj[k as keyof typeof obj].toUpperCase()); // okay
}
这里,k as keyof typeof obj
是类型断言。我们必须小心不要这样欺骗编译器,但只要我们小心,那就没问题。
为了完整性,您还可以在循环外声明 k
并为其指定一个更窄的类型;这相当于类型安全方面的类型断言:
let k: keyof typeof obj;
for (k in obj) {
console.log(obj[k as keyof typeof obj].toUpperCase()); // okay
}
好的,希望对您有所帮助;祝你好运!