错误TS2339:属性' x'类型' Y'

时间:2016-07-12 09:29:31

标签: typescript

我不明白为什么此代码会生成TypeScript错误。 (它不是原始代码,有点派生,所以请忽略示例中的无意义):

Value =

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

  

错误TS2339:财产'主要'类型'图像'。

上不存在

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

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

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

我不想使用字符串来访问该属性。我该怎么办?

6 个答案:

答案 0 :(得分:14)

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

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

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

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

修改

你可以有一个地图实例的辅助类,如:

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

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

答案 1 :(得分:7)

正确的解决方法是在类型定义中添加属性,如@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;

答案 2 :(得分:4)

我不是Typescript的专家,但我认为主要的问题是访问数据的方式。看看您如何描述Images接口,您可以将任何键定义为String。

访问属性时,我认为“dot”语法(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]

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

答案 3 :(得分:2)

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

请参阅TypeScript 2.2 release note带有字符串索引签名的类型的虚拟属性。

答案 4 :(得分:0)

正确的解决方法是按照@Nitzan Tomer的说明在类型定义中添加属性。 但是,如果您想像使用JavaScript一样编写代码,也可以只将属性定义为any

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

答案 5 :(得分:0)

我在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>