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

b1uwtaje  于 2023-02-14  发布在  TypeScript
关注(0)|答案(7)|浏览(240)

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

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

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

我收到此错误(使用TypeScript 1.7.5):
错误TS2339:类型"Images"上不存在属性"main"。
当然,我可以这样写来消除这个错误:

return images["main"];

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

t5zmwmid

t5zmwmid1#

如果你希望能够访问images.main,那么你必须显式地定义它:

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

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

不能使用点表示法访问索引属性,因为typescript无法知道对象是否具有该属性。
然而,当你明确定义一个属性时,编译器就知道它在那里(或不在那里),它是否是可选的,以及它的类型是什么。

编辑

您可以为map示例创建一个helper类,类似于:

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

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

eh57zj3b

eh57zj3b2#

正确的修复方法是在类型定义中添加属性,如@Nitzan Tomer的答案所述。

(黑客)变通方案1

您可以将对象赋给类型为any的常量,然后调用“non-existing”属性。

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

也可以将其转换为any

return (oldObj as any).someProperty;

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

变通方案2

如果你不能修改原始类型,你可以考虑的另一件事是扩展类型如下:

interface NewType extends OldType {
  someProperty: string;
}

现在你可以把你的变量转换成NewType而不是any,虽然仍然不理想,但是比any更宽松,给了你更多的类型安全。

return (oldObj as NewType).someProperty;
9nvpjoqh

9nvpjoqh3#

我不是Typescript方面的Maven,但我认为主要的问题是访问数据的方式,看看你是如何描述你的Images接口的,你可以将任何键定义为String。
当访问一个属性时,“点”语法(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]
这可能是你唯一的选择。但是,再说一次,我不是打字Maven,如果有人知道一个更好的解决方案/解释发生了什么,请随时纠正我。

qyswt5oh

qyswt5oh4#

从TypeScript 2.2开始,允许使用点标记法访问索引属性。在示例中不会出现错误TS2339。
请参见TypeScript 2.2 release note中具有字符串索引签名的类型的 *Dotted属性 *。

9fkzdhlc

9fkzdhlc5#

可能不那么古怪的解决方案:

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

h7appiyu6#

正确的修复方法是在类型定义中添加属性,如@Nitzan Tomer所述。但是,如果你想编写几乎与JavaScript相同的代码,你也可以将属性定义为any

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

2ekbmq327#

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

相关问题