MrA*_*ike 1 javascript typescript phaser-framework
我知道有人问过这个问题,但仍然无法找到适合我的情况的解决方案。
我有一个文件,在其中定义了某些值,然后我要循环遍历它们。我在这部分代码中收到错误
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]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
投诉来自 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"
}};
Run Code Online (Sandbox Code Playgroud)
不确定我明白为什么会发生这种情况以及如何解决它。
让我们将其简化为一个最小的、可重现的示例。请随意将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; }'. */
}
Run Code Online (Sandbox Code Playgroud)
这里我们有一个obj带有三个键的对象。我们尝试使用循环迭代这些键for..in,但得到一个错误,您无法使用该错误k来索引obj. 为什么?这不是循环的重点吗for..in?
这里的问题是 TypeScript 中的对象类型是开放的或可扩展的,而不是封闭的或精确的。您可以在 TypeScript 中向对象添加额外的属性,而不会违反其类型。这在某些情况下非常有用:它允许您通过添加属性来扩展接口和子类。但在其他情况下这很痛苦:
编译器将其视为objtype 的值{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!
Run Code Online (Sandbox Code Playgroud)
没有错误,obj = hmm因为值hmm匹配{a: string, b: string, c: string}。该d属性不违反类型。因此,对于编译器所知的一切,for (const k in obj)将枚举"a"、"b"、"c",谁知道还有哪些其他string值。因此, 的类型k不是keyof typeof obj。这只是string。
{a: string, b: string, c: string}并且使用 类型的键进行索引是不安全的string。事实上,当hmm分配给 时obj,调用 时会出现运行时错误(12345).toUpperCase()。因此,编译器向您发出警告,即使不是很有用,也是正确的。
有关此问题答案的“官方”版本,请参阅microsoft/TypeScript#35847 。另请参阅为什么TypeScript 中不Object.keys()返回类型?keyof,这是同一个问题,除了使用Object.keys(obj).forEach(k => ...)代替for (const k in obj) {...}...并且它有相同的答案。
如果引入了确切的类型,那么也许这个问题就会消失。有一个功能请求:microsoft/TypeScript#12936。但看起来这不会很快发生。
那么,现在能做什么呢?好吧,如果我们确定obj不会有任何编译器不知道的额外键,我们可以将其视为精确类型,并告诉编译器不要担心它。这种“告诉编译器”采用类型断言的形式:
for (const k in obj) {
console.log(obj[k as keyof typeof obj].toUpperCase()); // okay
}
Run Code Online (Sandbox Code Playgroud)
这里,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
}
Run Code Online (Sandbox Code Playgroud)
好的,希望有帮助;祝你好运!
| 归档时间: |
|
| 查看次数: |
1521 次 |
| 最近记录: |