Property does not exist on intersection type. 在交叉类型上不存在该属性。
Property does not exist on intersection type. 在交叉类型上不存在该属性。
我不明白以下最小可重现示例中的错误:
interface Animal { properties: Array<{ foo: number }> } type Cat = Animal & { properties: Array<{ foo: number, bar: number }> } let cat : Cat = {} as any cat.properties[0].bar cat.properties.forEach(prop => prop.bar) // ^^^^^^^^ // 类型 '{ foo: number; }' 上不存在属性 'bar'。
我期望最后两行要么通过类型检查,要么失败。
为什么`cat.properties[0].bar`能通过类型检查,而最后一行不能?我真的需要一个类型转换来使最后一行工作吗?
我只想简单地为`Animal`接口及其子接口添加一些属性。
(Property does not exist on intersection type)这个问题出现的原因是在交叉类型上访问属性时,编译器无法确定该属性是否存在。交叉类型是将多个类型合并为一个类型,但在合并的过程中,可能会出现冲突,导致某些属性在合并后的类型中不存在。
解决这个问题的方法是使用类型断言或类型守卫来明确告诉编译器某个属性确实存在。类型断言可以使用as关键字,类型守卫可以使用类型判断语句(如typeof、instanceof等)。
具体的解决方法如下所示:
type Foo = (a: number) => string; type Bar = (a: string) => number; type Overload = Foo & Bar; declare var fn: Overload; (fn as Foo)(2); // string (fn as Bar)('str'); // number
在上面的代码中,我们使用类型断言将fn断言为Foo类型和Bar类型,以确保在调用fn时能够正确地推断出返回值的类型。
在实际开发中,当遇到类似的问题时,我们可以先检查交叉类型中是否存在某个属性,然后使用类型断言或类型守卫来访问该属性,以避免编译器报错。(Property does not exist on intersection type)问题的出现主要是因为在交叉类型上访问属性时,编译器无法确定该属性是否存在。通过使用类型断言或类型守卫,我们可以明确告诉编译器该属性确实存在,从而解决这个问题。
(Property does not exist on intersection type)这个问题的出现原因是因为在代码中的intersection type(交叉类型)上不存在某个属性。在给定的代码中,使用了交叉类型来定义Cat接口,它继承了Animal接口,并在其中重新定义了properties属性。然而,由于交叉类型的特性,它会将两个接口的属性合并,但是在实际使用中,Cat接口的properties属性被认为是Animal接口中的属性,导致在访问Cat类型的实例时,会出现(Property does not exist on intersection type)的错误。
为了解决这个问题,可以改变代码中的类型定义。首先,可以为不同种类的属性声明不同的类型,这样在使用的时候更加清晰。另外,需要将所有的类型都进行导出,以便在其他地方使用。
此外,不要使用as any
,因为这样会导致代码在很多方面出现问题。如果某个属性是可选的,应该将其标记为可选,例如properties?: AnimalProperty[]
。
下面是修改后的代码示例:
export interface AnimalProperty { foo: number; } export interface CatProperty extends AnimalProperty { bar: number; } export interface Animal { properties: AnimalProperty[]; } export interface Cat extends Animal { catProperties: CatProperty[]; } const cat: Cat = { properties: [], catProperties: [] };
通过以上的修改,我们在Cat接口中新增了一个catProperties属性,用来代表Cat类型独有的属性。这样,在访问Cat类型的实例时就不会出现(Property does not exist on intersection type)的错误了。
问题的出现原因是由于存在相同的属性名称,并且交叉类型在处理冲突时与扩展类型的处理方式不同。TypeScript 不知道应该使用哪一个属性,因此会选择其中一个。
在这里,他们提到冲突的处理方式不同,可以参考这个链接:https://www.typescriptlang.org/docs/handbook/2/objects.html#interfaces-vs-intersections 这似乎与你的情况完全相符。
如果你想要覆盖属性,可以参考这个链接:https://stackoverflow.com/a/54774013/10691359
相反,如果你扩展你的 Animal 类型,那么属性的重载检测将会很好,并且你将可以访问 bar 属性。
interface CatA extends Animal { properties: Array<{ foo: number, bar: number }> } let catA: CatA = {} as any; catA.properties[0].bar catA.properties.forEach(prop => prop.bar)
总结起来,解决这个问题的方法是通过扩展类型或者使用覆盖属性的方式来处理冲突。