我有以下页面对象模型,表示我的应用程序中的一个小部件

/**
 * Contains common actions for all widgets
 */

export default abstract class AbstractWidget {
  private widgetId: number;

  elements = {
    widget: () => cy.getDataTestId(`widgetbox-container-${this.widgetId}`),
  };

  constructor(widgetId: number) {
    this.widgetId = widgetId;
  }
  
}

我有一个扩展这个类的具体类,我想在其中将特定于此小部件的额外元素附加到elements属性

import AbstractWidget from './AbstractWidget';

export default class SpecificWidget extends AbstractWidget {
    elements = {
        ...super.elements,
        assetSearch: () => cy.getDataTestId('assetSearch'),
    };


    constructor(widgetId: number) {
        super(widgetId);
    }
}

然而,当我try 从抽象超类中传播元素时

    elements = {
        ...super.elements,
        assetSearch: () => cy.getDataTestId('assetSearch'),
    };

这会导致打字错误

TS2340: Only public and protected methods of the base class are accessible via the  super  keyword.

我做错了什么?

推荐答案

This seems to be a result of this issue
Accessing property on super should be a type error #35314 Nov 24, 2019

如果您点击TS Playground链接,它将以最新的TS版本打开,console.log(super.n)显示错误.如果您将版本更改为3.7.5,则错误将消失.

但是,如果您查看手册Overriding Methods,则允许对101进行同等访问,因此上面的更改似乎造成了异常

class Base {
  greet() {
    console.log("Hello, world!");
  }
}
 
class Derived extends Base {
  greet(name?: string) {
    if (name === undefined) {
      super.greet();
    } else {
      console.log(`Hello, ${name.toUpperCase()}`);
    }
  }
}

具体而言,在Cypress中,您可以使用this.elements而不是super.elements,因为派生类继承了基类元素属性:

Testing (with string return values instead of Chainers)

export default class SpecificWidget extends AbstractWidget {
  elements = {
    ...this.elements,
    assetSearch: () => 'assetSearch',
  }

  constructor(widgetId: number) {
    super(widgetId)
  }
}
export default abstract class AbstractWidget {
  private widgetId: number

  elements = {
    widget: () => `widgetbox-container-${this.widgetId}`,
  }

  constructor(widgetId: number) {
    this.widgetId = widgetId
  }
}
const specific = new SpecificWidget(1)
expect(specific.elements.widget()).to.eq('widgetbox-container-1')
expect(specific.elements.assetSearch()).to.eq('assetSearch')

enter image description here


或者你可以在基类中创建一个"helper方法"

export default abstract class AbstractWidget {
  private widgetId: number

  elements = {
    widget: () => `widgetbox-container-${this.widgetId}`,
  }

  getElements() {
    return this.elements
  }

  constructor(widgetId: number) {
    this.widgetId = widgetId
  }
}
export default class SpecificWidget extends AbstractWidget {
  elements = {
    ...super.getElements(),
    assetSearch: () => 'assetSearch',
  }

  constructor(widgetId: number) {
    super(widgetId)
  }
}

另请注意,像这样返回Chainers

widget: () => cy.getDataTestId(`widgetbox-container-${this.widgetId}`),

如果返回的Chainer由于页面更改而无效,则可能导致意外问题.

Variables and aliases - Return values

Return Values
You cannot assign or work with the return values of any Cypress command. Commands are enqueued and run asynchronously.

如果您打算在调用widgit()和使用结果之间立即链接而没有页面操作,这是可以的,但这意味着任何使用该类的人都必须记住这一点.

Cypress专门针对这个问题将默认值更改为type: query.

如果别名在使用时变得陈旧,则重新运行chainer以获取查询结果的新副本.但这不会自动发生在你的100.

Typescript相关问答推荐

根据第一个参数的值设置第二个参数的类型

如何传递基于TypScript中可变类型的类型?

在类型内部使用泛型类型时,不能使用其他字符串索引

如何在第一次加载组件时加载ref数组

TypeScript Page Routing在单击时不呈现子页面(React Router v6)

数组文字中对象的从键开始枚举

打字脚本中泛型和直接类型重新映射的不同行为

如何在Reaction路由v6.4加载器和操作中获得Auth0访问令牌?

为什么在这个例子中,我把缺少的属性添加到对象中时,TypeScrip没有拾取,如何修复?

是否可以基于对象的S属性值[]约束对象的其他属性值用于类型化的对象数组?

嵌套对象的类型

推断从其他类型派生的类型

使用条件类型的类型保护

编译TypeScrip项目的一部分导致错误

TypeScrip:使用Union ToInterval辅助对象,但保留子表达式

17个Angular 的延迟观察.如何在模板中转义@符号?

如何正确地将元组表格输入到对象数组实用函数(如ZIP)中,避免在TypeScrip 5.2.2中合并所有值

如何根据Typescript 中带有泛型的对象嵌套键数组获取数组或对象的正确类型?

React-Router V6 中的递归好友路由

如何确定剧作家中给定定位器的值?