简体   繁体   English

元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型 - Phaser

[英]Element implicitly has an 'any' type because expression of type 'string' can't be used to index type - Phaser

I know this has been asked, but still can't figure out a solution for my case.我知道这已被问到,但仍然无法为我的案例找到解决方案。

I have a file where I define certain values and then I was to loop thru them.我有一个文件,我在其中定义了某些值,然后我要遍历它们。 I get the error in this part of the code我在这部分代码中得到错误

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]);                
        }
    }
}

The complain comes on the STATIC.IMAGES[key] calls.投诉来自 STATIC.IMAGES[key] 调用。 And STATIC comes from a file with而 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"
}};

Not sure I understand why this happens and how to fix it.不知道我理解为什么会发生这种情况以及如何解决它。

Let's pare that down into a minimal, reproducible example .让我们将其缩减为一个最小的、可重现的示例 Feel free to replace obj below with your STATIC.IMAGES ;随意用您的STATIC.IMAGES替换下面的obj it's the same explanation either way:无论哪种方式都是相同的解释:

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; }'. */
}

Here we have an object obj with three keys.这里我们有一个带有三个键的 object obj We try to iterate over those keys with a for..in loop and we get an error that you can't use k to index into obj .我们尝试使用for..in循环遍历这些键,我们得到一个错误,您不能使用k来索引obj Why?为什么? Isn't that the point of for..in loops?这不是for..in循环的重点吗?


The problem here is that object types in TypeScript are open or extendible , and not closed or exact .这里的问题是 TypeScript 中的 object 类型是开放的或可扩展的,而不是封闭的或精确的 You can add extra properties to an object in TypeScript without violating its type.您可以向 TypeScript 中的 object 添加额外属性,而不会违反其类型。 This is great in some situations: it allows you to extend interfaces and subclass classes by adding properties.这在某些情况下非常有用:它允许您通过添加属性来扩展接口和子类。 But in other situations it's a pain:但在其他情况下,这很痛苦:

The compiler sees obj as a value of type {a: string, b: string, c: string} .编译器将obj视为{a: string, b: string, c: string}类型的值。 Since this type is not exact, when you do for (const k in obj) , the compiler knows that k will take on values "a" , "b" , and "c" , but it doesn't know that those are the only possible values:由于这种类型不准确,当您执行for (const k in obj)时,编译器知道k将采用值"a""b""c" ,但它知道这些是只有可能的值:

let hmm = { a: "hey", b: "you", c: "guys", d: 12345 };
obj = hmm; // no error!

There's no error in obj = hmm because the value hmm matches {a: string, b: string, c: string} . obj = hmm没有错误,因为值hmm匹配{a: string, b: string, c: string} The d property does not violate the type. d属性不违反类型。 So, for all the compiler knows, for (const k in obj) will enumerate "a" , "b" , "c" , and who knows what other string values .所以,就编译器所知, for (const k in obj)将枚举"a""b""c"谁知道还有哪些其他string Therefore, the type of k is not keyof typeof obj .因此, k的类型不是keyof typeof obj It is just string .它只是string

And it's not safe to index into {a: string, b: string, c: string} with a key of type string .使用 string 类型的键索引{a: string, b: string, c: string} string不安全的。 Indeed, with hmm assigned to obj , there will be a runtime error calling (12345).toUpperCase() .实际上,将hmm分配给obj时,调用(12345).toUpperCase()将会出现运行时错误。 So it's correct, if not very useful, for the compiler to warn you.所以编译器警告你是正确的,如果不是很有用的话。

See microsoft/TypeScript#35847 for an "official" version of the answer to this question.有关此问题答案的“官方”版本,请参阅microsoft/TypeScript#35847 Also see Why doesn't Object.keys() return a keyof type in TypeScript?另请参阅为什么Object.keys()不返回 TypeScript 中的keyof类型? , which is the same question except using Object.keys(obj).forEach(k =>...) instead of for (const k in obj) {...} ... and it has the same answer. ,这是相同的问题,除了使用Object.keys(obj).forEach(k =>...)而不是for (const k in obj) {...} ... 并且它具有相同的答案。

If exact types are ever introduced, then maybe this problem would just go away.如果曾经引入确切的类型,那么这个问题可能只是 go 了。 There is a feature request for this: microsoft/TypeScript#12936 .对此有一个功能请求: microsoft/TypeScript#12936 But it doesn't look like this is going to happen any time soon.但看起来这不会很快发生。


For now, then, what can be done?那么,就目前而言,能做些什么呢? Well, if we know for sure that obj won't have any extra keys that the compiler doesn't know about, we can treat it as if it were an exact type and just tell the compiler not to worry about it.好吧,如果我们确定obj不会有任何编译器不知道的额外键,我们可以将它视为一个精确类型,并告诉编译器不要担心它。 This "telling the compiler" takes the form of a type assertion :这种“告诉编译器”采用类型断言的形式:

for (const k in obj) {
  console.log(obj[k as keyof typeof obj].toUpperCase()); // okay
}

Here, k as keyof typeof obj is the type assertion.这里, k as keyof typeof obj是类型断言。 We have to be careful not to lie to the compiler this way, but as long as we are careful, then it's fine.我们必须小心,不要这样对编译器撒谎,但只要我们小心,就可以了。


For completeness you can also declare k outside the loop and give it a narrower type;为了完整起见,您还可以在循环之外声明k并给它一个更窄的类型; this is equivalent to the type assertion in terms of type safety:这在类型安全方面等价于类型断言:

let k: keyof typeof obj;
for (k in obj) {
  console.log(obj[k as keyof typeof obj].toUpperCase()); // okay
}

Okay, hope that helps;好的,希望有帮助; good luck!祝你好运!

Playground link to code Playground 代码链接

暂无
暂无

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

相关问题 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“BGColors” - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'BGColors' 如何修复 Element 隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型? - how fix Element implicitly has an 'any' type because expression of type 'string' can't be used to index type? 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型 React Typescript - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type React Typescript 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“{}” - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}' 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“{ AT: number; BE:数字,...}` - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ AT: number; BE: number,…}` 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型 A - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type A 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型样式 - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type style TypeScript - 元素隐式具有“任意”类型,因为“字符串”类型的表达式不能用于索引类型 - TypeScript - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“{}” - Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}' TypeScript - ts(7053):元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引 - TypeScript - ts(7053) : Element implicitly has an 'any' type because expression of type 'string' can't be used to index
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM