ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

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

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

return images["main"];

我宁愿不使用字符串来访问该属性。我能做些什么?

键入 images["main"] 不会引发错误?
不,`images["main"] 没问题。
@basarat 当 TS 编译器不以人们期望的方式使用它时,这些定义有什么用?

{{display_vari_price}}

价格:{{ slide.price }}

报价:{{slide.saleprice}}

属性此组件上不存在第二个

N
Nitzan Tomer

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

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

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

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

编辑

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

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

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


首先:这是一个有用的答案,可能是我的问题的解决方案。但是接下来:用 [key: string]: aType 声明“类似地图”的对象是什么意思?
从这个意义上说,地图就像一个数组,您可以使用括号访问元素
我添加了另一种处理地图的方式,检查我修改后的答案
C
Community

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

(Hacky) 解决方法 1

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

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

您也可以将其转换为 any

return (oldObj as any).someProperty;

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

(Hacky) 解决方法 2

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

interface NewType extends OldType {
  someProperty: string;
}

现在您可以将变量转换为此 NewType 而不是 any。仍然不理想,但不如 any 宽松,为您提供更多类型安全性。

return (oldObj as NewType).someProperty;

{{display_vari_price}}

价格:{{ slide.price }}

报价:{{slide.saleprice}}

属性此组件上不存在第二个
Y
Yassine Badache

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

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

return json.property[0].index

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

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

而且我必须使用您的语法找到解决方法:

return json.property[0][index]

那里可能是您唯一的选择。但是,再一次,我不是打字稿专家,如果有人知道更好的解决方案/解释会发生什么,请随时纠正我。


这是一个完全不同的问题。
您在问您能做什么/为什么会出现错误。我试图向您解释为什么会出现此错误,以及考虑到我的个人知识,您可以选择什么。如前所述,任何人都可以有更好的答案,我正在努力提供帮助。在您的 Images 界面中未定义 main 属性绝对是您的问题。
不,这不是问题。属性“main”存在。这不是运行时问题,而是编译时问题。而且我不是通过变量访问属性,但“main”实际上是属性的名称。
很高兴它在这里至少帮助了一个人:)。
我在 req.header.mod_api_key = 'somevalue' 上收到错误 TS2339 但 req.header['mod_api_key'] = 'somevalue' 没有给我错误。常量 a='mod_api_key'; req.header[a] 也有效。
a
aleung

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

请参阅 TypeScript 2.2 release note 中具有字符串索引签名的类型的点属性


W
Whenever

据说不那么hacky的解决方案:

if ("property" in obj) {
  console.log(`Can access ${obj.property}`)
}


请提供解释。请参阅How to answer
A
Andris

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

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

{{display_vari_price}}

价格:{{ slide.price }}

报价:{{slide.saleprice}}

属性此组件上不存在第二个
s
stanimirsp

我在 Vue 3 上遇到了这个错误。这是因为必须像这样导入 defineComponent

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
    name: "HelloWorld",
    props: {
        msg: String,
    },
    created() {
        this.testF();
    },
    methods: {
        testF() {
            console.log("testF");
        },
    },
});
</script>