typescript 错误 TS2339:类型“Y”上不存在属性“x”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38324949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:13:32  来源:igfitidea点击:

error TS2339: Property 'x' does not exist on type 'Y'

typescript

提问by hgoebl

I don't understand why this code generates TypeScript error. (It's not the original code and is a bit derived, so please ignore the non-sense in the example):

我不明白为什么这段代码会产生 TypeScript 错误。(这不是原始代码,有点衍生,所以请忽略示例中的废话):

interface Images {
  [key:string]: string;
}

function getMainImageUrl(images: Images): string {
  return images.main;
}

I'm getting error (using TypeScript 1.7.5):

我收到错误(使用 TypeScript 1.7.5):

error TS2339: Property 'main' does not exist on type 'Images'.

错误 TS2339:“图像”类型上不存在属性“main”。

Of course I could get rid of the error when writing:

当然,我可以在编写时摆脱错误:

return images["main"];

I'd prefer not using string to access the property. What can I do?

我不希望使用字符串来访问该属性。我能做什么?

采纳答案by Nitzan Tomer

If you want to be able to access images.mainthen you must define it explicitly:

如果您希望能够访问,images.main那么您必须明确定义它:

interface Images {
    main: string;
    [key:string]: string;
}

function getMainImageUrl(images: Images): string {
    return images.main;
}

You can not access indexed properties using the dot notation because typescript has no way of knowing whether or not the object has that property.
However, when you specifically define a property then the compiler knows that it's there (or not), whether it's optional or not and what's the type.

您不能使用点表示法访问索引属性,因为打字稿无法知道对象是否具有该属性。
但是,当您专门定义一个属性时,编译器就会知道它是否存在(或不存在),无论它是否可选以及类型是什么。



Edit

编辑

You can have a helper class for map instances, something like:

您可以为地图实例创建一个辅助类,例如:

class Map<T> {
    private items: { [key: string]: T };

    public constructor() {
        this.items = Object.create(null);
    }

    public set(key: string, value: T): void {
        this.items[key] = value;
    }

    public get(key: string): T {
        return this.items[key];
    }

    public remove(key: string): T {
        let value = this.get(key);
        delete this.items[key];
        return value;
    }
}

function getMainImageUrl(images: Map<string>): string {
    return images.get("main");
}

I have something like that implemented, and I find it very useful.

我已经实现了类似的东西,我发现它非常有用。

回答by Nelu

The correct fix is to add the property in the type definition as explained in @Nitzan Tomer's answer. If that's not an option though:

正确的解决方法是在类型定义中添加属性,如@Nitzan Tomer 的回答中所述。如果这不是一个选项:

(Hacky) Workaround 1

(Hacky) 解决方法 1

You can assign the object to a constant of type any, then call the 'non-existing' property.

您可以将对象分配给any类型的常量,然后调用“不存在”属性。

const newObj: any = oldObj;
return newObj.someProperty;

You can also cast it as any:

您也可以将其转换为any

return (oldObj as any).someProperty;

This fails to provide any type safety though, which is the point of TypeScript.

但是,这无法提供任何类型安全性,这正是 TypeScript 的重点。



(Hacky) Workaround 2

(Hacky) 解决方法 2

Another thing you may consider, if you're unable to modify the original type, is extending the typelike so:

如果您无法修改原始类型,您可能会考虑的另一件事是像这样扩展类型

interface NewType extends OldType {
  someProperty: string;
}

Now you can cast your variable as this NewTypeinstead of any. Still not ideal but less permissive than any, giving you more type safety.

现在您可以将变量转换为 thisNewType而不是any. 仍然不理想但比 宽松any,给你更多的类型安全。

return (oldObj as NewType).someProperty;

回答by Yassine Badache

I'm no expert in Typescript, but I think the main problem is the way of accessing data. Seeing how you described your Imagesinterface, you can define any key as a String.

我不是 Typescript 专家,但我认为主要问题是访问数据的方式。查看您如何描述您的Images界面,您可以将任何键定义为字符串。

When accessing a property, the "dot" syntax (images.main) supposes, I think, that it already exists. I had such problems without Typescript, in "vanilla" Javascript, where I tried to access data as:

在访问属性时,“点”语法 ( images.main) 假设它已经存在。我在没有 Typescript 的情况下遇到了这样的问题,在“vanilla”Javascript 中,我尝试访问数据:

return json.property[0].index

return json.property[0].index

where index was a variable. But it interpreted index, resulting in a:

其中 index 是一个变量。但它解释了index,导致:

cannot find property "index" of json.property[0]

cannot find property "index" of json.property[0]

And I had to find a workaround using your syntax:

我不得不使用您的语法找到一种解决方法:

return json.property[0][index]

return json.property[0][index]

It may be your only option there. But, once again, I'm no Typescript expert, if anyone knows a better solution / explaination about what happens, feel free to correct me.

这可能是你唯一的选择。但是,再一次,我不是 Typescript 专家,如果有人知道关于发生的事情的更好的解决方案/解释,请随时纠正我。

回答by aleung

Starting with TypeScript 2.2 using dot notation to access indexed properties is allowed. You won't get error TS2339 on your example.

从 TypeScript 2.2 开始,允许使用点表示法访问索引属性。您不会在示例中收到错误 TS2339。

See Dotted property for types with string index signaturesin TypeScript 2.2 release note.

的类型与串指数签名点缀性质打字稿2.2版本注释

回答by Andris

The correct fix is to add the property in the type definition as explained by @Nitzan Tomer. But also you can just define property as any, if you want to write code almost as in JavaScript:

正确的解决方法是在类型定义中添加属性,如@Nitzan Tomer 所述。但是any,如果您想编写几乎像在 JavaScript 中一样的代码,您也可以将属性定义为:

arr.filter((item:any) => {
    return item.isSelected == true;
}