Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
typescript中的默认泛型类型_Typescript_Protractor - Fatal编程技术网

typescript中的默认泛型类型

typescript中的默认泛型类型,typescript,protractor,Typescript,Protractor,所以我有一个量角器列表页面对象。该对象默认返回ElementFinder实例,但可以自定义为返回ComplexType实例,如下所示: class ComplexType { foo = 'foo'; constructor(public element: ElementFinder) {} } const list = new List<ComplexType>({ element: ..., type: ComplexType}); expect(list.get(0

所以我有一个量角器列表页面对象。该对象默认返回
ElementFinder
实例,但可以自定义为返回
ComplexType
实例,如下所示:

class ComplexType {
  foo = 'foo';

  constructor(public element: ElementFinder) {}
}

const list = new List<ComplexType>({ element: ..., type: ComplexType});
expect(list.get(0).foo).toBe('foo');
类ComplexType{
foo=‘foo’;
构造函数(公共元素:ElementFinder){}
}
常量列表=新列表({element:…,type:ComplexType});
expect(list.get(0.foo).toBe('foo');
以下是页面对象定义:

import { ElementFinder } from 'protractor';

export interface ListItem<T> {
  new(element: ElementFinder): T;
}

export interface ListOptions<T> {
  element: ElementFinder;
  selector?: string;
  type?: ListItem<T>;
}

export class List<T = ElementFinder> {
  public readonly element: ElementFinder;
  private selector: string;
  private type: (element: ElementFinder) => T;

  get items() {
    return this.element.$$(this.selector);
  }

  get length() {
    return this.items.count();
  }

  constructor(options: ListOptions<T> | ElementFinder, selector?: string) {
    if (options instanceof ElementFinder) {
      this.element = options;
      this.selector = selector || 'li';
      this.type = (element: ElementFinder) => element;
    } else {
      this.element = options.element;
      this.selector = options.selector || 'li';
      this.type = (element: ElementFinder) => new options.type(element);
    }
  }

  get(index: number): T {
    return this.type(this.items.get(index));
  }
}
从“量角器”导入{ElementFinder};
导出接口列表项{
新(元素:ElementFinder):T;
}
导出接口列表选项{
元素:ElementFinder;
选择器?:字符串;
类型?:列表项;
}
导出类列表{
公共只读元素:ElementFinder;
私有选择器:字符串;
私有类型:(element:ElementFinder)=>T;
获取项目(){
返回this.element.$$(this.selector);
}
获取长度(){
返回此.items.count();
}
构造函数(选项:ListOptions | ElementFinder,选择器?:字符串){
if(ElementFinder的选项实例){
this.element=选项;
this.selector=selector||'li';
this.type=(元素:ElementFinder)=>元素;
}否则{
this.element=options.element;
this.selector=options.selector | |“li”;
this.type=(元素:ElementFinder)=>newoptions.type(元素);
}
}
get(索引:number):T{
返回this.type(this.items.get(index));
}
}
我遇到的问题是typescript不理解t有时是ElementFinder。因此,当我返回ElementFinder的实例时,它会抱怨ElementFinder与T不匹配


我被难住了。当然这是可能的?

问题是,在类中,
T
是不特定的(即使您进行一些检查,编译器也不会以任何方式缩小
T
)。这意味着所有的赋值都必须适用于任何可能的
T
,因为
this.type=(element:ElementFinder)=>元素对任何
T
都不起作用,它将给出一个错误

如果我们确定这是一个误报,那么快速而肮脏的修复方法是使用类型断言:

this.type = (element: ElementFinder) => element as any;
更优雅的解决方案是将
类型更改为required,并传入相应的函数:

class ComplexType {
    foo = 'foo';

    constructor(public element: ElementFinder) { }
}

export interface ListOptions<T> {
    element: ElementFinder;
    selector?: string;
    type: (element: ElementFinder) => T;
}

export class List<T = ElementFinder> {
    public readonly element: ElementFinder;
    private selector: string;
    private type: (element: ElementFinder) => T;

    get items() {
        return this.element.$$(this.selector);
    }

    get length() {
        return this.items.count();
    }
    public static default(element: ElementFinder, selector = 'li') :ListOptions<ElementFinder>{
        return {
            element,
            selector,
            type : (e) => e
        }
    }
    constructor(options: ListOptions<T>, selector?: string) {
        this.element = options.element;
        this.selector = options.selector || 'li';
        this.type = options.type;
    }

    get(index: number): T {
        return this.type(this.items.get(index));
    }
}
let element!: ElementFinder;

// complex usage
const list1 = new List<ComplexType>({ element, type: e=> new ComplexType(e) });
//default usage
const list2 = new List(List.default(element));
类ComplexType{
foo=‘foo’;
构造函数(公共元素:ElementFinder){}
}
导出接口列表选项{
元素:ElementFinder;
选择器?:字符串;
类型:(元素:ElementFinder)=>T;
}
导出类列表{
公共只读元素:ElementFinder;
私有选择器:字符串;
私有类型:(element:ElementFinder)=>T;
获取项目(){
返回this.element.$$(this.selector);
}
获取长度(){
返回此.items.count();
}
公共静态默认值(元素:ElementFinder,选择器='li'):ListOptions{
返回{
元素,
选择器,
类型:(e)=>e
}
}
构造函数(选项:列表选项,选择器?:字符串){
this.element=options.element;
this.selector=options.selector | |“li”;
this.type=options.type;
}
get(索引:number):T{
返回this.type(this.items.get(index));
}
}
让元素!:元素查找器;
//复杂用法
constlist1=新列表({element,type:e=>newcomplextype(e)});
//默认用法
const list2=新列表(List.default(element));

谢谢您的解释!