错误 TS2339:类型“Y”上不存在属性“x”
Posted
技术标签:
【中文标题】错误 TS2339:类型“Y”上不存在属性“x”【英文标题】:error TS2339: Property 'x' does not exist on type 'Y' 【发布时间】:2016-11-14 11:07:28 【问题描述】:我不明白为什么这段代码会产生 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
如果您希望能够访问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
声明“类似地图”的对象是什么意思?
这个意义上的地图就像一个数组,你用括号访问元素
我添加了另一种处理地图的方式,查看我修改后的答案【参考方案2】:
正确的解决方法是在类型定义中添加属性,如@Nitzan Tomer 的回答中所述。如果那不是一个选项:
(Hacky)解决方法 1
您可以将对象分配给 any 类型的常量,然后调用“不存在”属性。
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
我不是 Typescript 方面的专家,但我认为主要问题是访问数据的方式。看到您如何描述您的Images
接口,您可以将任何键定义为字符串。
访问属性时,我认为“点”语法 (images.main
) 假设它已经存在。我在没有 Typescript 的情况下遇到了这样的问题,在“香草”javascript 中,我尝试访问数据:
return json.property[0].index
其中 index 是一个变量。但它解释了index
,导致:
cannot find property "index" of json.property[0]
我必须使用您的语法找到解决方法:
return json.property[0][index]
这可能是您唯一的选择。但是,再一次,我不是 Typescript 专家,如果有人知道更好的解决方案/解释发生了什么,请随时纠正我。
【讨论】:
这是一个完全不同的问题。 你在问你能做什么/为什么你有错误。我试图向您解释为什么会出现此错误,以及考虑到我的个人知识,您可以选择什么。如前所述,任何人都可以有更好的答案,我正在努力提供帮助。Images
接口中未定义 main
属性绝对是您的问题。
不,不是问题。属性“main”存在。这不是运行时问题,而是编译时问题。而且我不是通过变量访问属性,但“main”实际上是属性的名称。
很高兴它在这里至少帮助了一个人:)。
我在 req.header.mod_api_key = 'somevalue' 上收到错误 TS2339 但 req.header['mod_api_key'] = 'somevalue' 没有给我错误。常量 a='mod_api_key'; req.header[a] 也有效。【参考方案4】:
从 TypeScript 2.2 开始,允许使用点表示法访问索引属性。您的示例不会出现错误 TS2339。
请参阅TypeScript 2.2 release note 中带有字符串索引签名的类型的点属性。
【讨论】:
【参考方案5】:正确的解决方法是在类型定义中添加属性,如@Nitzan Tomer 所述。
但也可以将属性定义为any
,如果您想编写代码几乎就像在 JavaScript 中一样:
arr.filter((item:any) =>
return item.isSelected == true;
【讨论】:
display_vari_price
价格: slide.price
报价:slide.saleprice
我在 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>
【讨论】:
【参考方案7】:对我有帮助的是把变量变成公共变量,在这个例子中:
interface Images
public[key:string]: string;
function getMainImageUrl(images: Images): string
return images.main;
【讨论】:
【参考方案8】:据说不那么 hacky 的解决方案:
if ("property" in obj)
console.log(`Can access $obj.property`)
【讨论】:
请提供解释。见How to answer。以上是关于错误 TS2339:类型“Y”上不存在属性“x”的主要内容,如果未能解决你的问题,请参考以下文章
错误 TS2339:类型“”上不存在属性“contenido”
TypeScript:TS2339 错误——“对象”类型上不存在属性