我不明白为什么这段代码会生成 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
,则必须明确定义它:
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");
}
我已经实现了类似的东西,我发现它非常有用。
正确的解决方法是在类型定义中添加属性,如@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;
我不是 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
属性绝对是您的问题。
从 TypeScript 2.2 开始,允许使用点表示法访问索引属性。您的示例不会出现错误 TS2339。
请参阅 TypeScript 2.2 release note 中具有字符串索引签名的类型的点属性。
据说不那么hacky的解决方案:
if ("property" in obj) {
console.log(`Can access ${obj.property}`)
}
正确的解决方法是在类型定义中添加属性,如@Nitzan Tomer 所述。但也可以将属性定义为 any
,如果您想几乎像在 JavaScript 中一样编写代码:
arr.filter((item:any) => {
return item.isSelected == true;
}
我在 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>
[key: string]: aType
声明“类似地图”的对象是什么意思?