Javascript 如何重写不提供与签名匹配的泛型构造函数的定义

Javascript 如何重写不提供与签名匹配的泛型构造函数的定义,javascript,typescript,generics,constructor,interface,Javascript,Typescript,Generics,Constructor,Interface,我正在编写一个库来实现JavaScript中iterable类型的延迟计算查询。我知道已经有可用的选项可以实现这一点,但我的选择是采用完全不同的方法来公开扩展方法 我在处理一个特殊的设计挑战时遇到了困难,我想知道是否有一些我没有想到的解决问题的方法 我的可枚举类定义及其接口以及一些帮助程序如下所示: // Iterator<T> defined in lib.es2015.iterable.d.ts interface IteratorFunction<T> { (t

我正在编写一个库来实现JavaScript中iterable类型的延迟计算查询。我知道已经有可用的选项可以实现这一点,但我的选择是采用完全不同的方法来公开扩展方法

我在处理一个特殊的设计挑战时遇到了困难,我想知道是否有一些我没有想到的解决问题的方法

我的
可枚举
类定义及其接口以及一些帮助程序如下所示:

// Iterator<T> defined in lib.es2015.iterable.d.ts
interface IteratorFunction<T> {
  (this: IEnumerable<T> | void): Iterator<T>
}

interface CompareFunction<T> {
  (a: T, b: T): number
}

// inspired by pattern for ArrayConstructor in lib.es5.d.ts
interface IEnumerableConstructor {
  new <T>(iterator: IteratorFunction<T>): IEnumerable<T>
  new <T>(iterator: IteratorFunction<T>, compare: null): IEnumerable<T>
  new <T>(iterator: IteratorFunction<T>, compare: CompareFunction<T>): IOrderedEnumerable<T>

  // static methods...
}

// Symbol.compare defined in separate file as a declaration merge to SymbolConstructor
interface IOrderedEnumerable<T> extends IEnumerable<T> {
  readonly [Symbol.compare]: CompareFunction<T>

  // overrides for thenBy()...
}

// IterableIterator<T> defined in lib.es2015.iterable.d.ts
interface IEnumerable<T> extends IterableIterator<T> {
  // member methods...
}

class Enumerable<T> implements IEnumerableConstructor {
  readonly [Symbol.iterator]: IteratorFunction<T>
  readonly [Symbol.compare]: (null | CompareFunction<T>)

  constructor (iterator: IteratorFunction<T>)
  constructor (iterator: IteratorFunction<T>, compare: (null | CompareFunction<T>) = null) {
    this[Symbol.iterator] = iterator
    this[Symbol.compare] = compare
  }
}
为了澄清,我声明了
TypedArray
作为
Int8Array
等根据ECMAScript规范扩展的类(但是TypeScript
lib.*.d.ts
文件中没有提供它的类型,因为它从未直接使用过,这是可以理解的)


正如我所说的,这个库实现是一种与将扩展方法公开给内置JavaScript完全不同的方法,我知道所有的缺陷,但现在我正在寻找一种方法来为类
可枚举
构造函数提供一个定义,它尊重
IEnumerable
的泛型。有什么想法吗?

IEnumerableConstructor
有构造签名

但在TypeScript中,类不需要显式声明为实现某个接口——毕竟,类型系统是结构化的,只要接口兼容,就可以在需要接口的地方使用类

根据我在代码中的理解,
Enumerable
实际上必须实现
IEnumerable
,因为
接口IEnumerableConstructor
中的构造签名声明生成的就是这种类型。因此它应该有
next()
方法,如果您只是省略
implements IEnumerableConstructor
,它似乎可以工作(但如果您将其替换为
implements IEnumerable
,以使编译器检查类是否正确实现了该接口,则不会有任何影响):

类可枚举实现了IEnumerable{
只读[符号.迭代器]:迭代器函数
只读比较:(空|比较函数)
构造函数(迭代器:迭代器函数)
构造函数(迭代器:迭代器函数,比较?:(null |比较函数)){
此[Symbol.iterator]=迭代器
比较
}
next():IteratorResult{
返回未定义;
}
}
常数C:IEnumerableConstructor=可枚举;
类型A={A:string};
让a:a[];
常数c=新的c(a.值);//推断为常数c:IEnumerable

谢谢,方法不是问题,因为为了简洁起见,我省略了那些声明和定义。然而,当我试图让它工作时,我不得不从
接口IEnumerable
中删除
扩展IterableIterator
,否则分配给
这个[Symbol.iterator]
会有冲突。我还没有测试我是否仍然可以通过一个
IEnumerable
作为
for…of
循环的目标,但当我到达它时,我可以跨越这座桥。谢谢你的解释!我最近又在做这件事,我意识到了一些重要的事情。使用内置库定义作为参考,标准做法似乎是从
接口
中省略
构造函数
签名,而在接口的相应
…构造函数
接口中使用
新的
签名。其次,我注意到,
IEnumerable
的唯一目的是定义
Enumerable
的子集,即
数组
映射
字符串
类型数组
constructor (iterator: IteratorFunction<T>)
new (iterator: IteratorFunction<T>): IEnumerable<T>
new <T>(iterator: IteratorFunction<T>): IEnumerable<T>
declare global {
  // ...

  interface ArrayConstructor extends IEnumerableConstructor/*<T>*/ { } // illegal!
  interface MapConstructor extends IEnumerableConstructor { }
  interface SetConstructor extends IEnumerableConstructor { }
  interface StringConstructor extends IEnumerableConstructor { }
  interface TypedArrayConstructor extends IEnumerableConstructor { }

  interface Array<T> extends IEnumerable<T> { }
  interface Map<K, V> extends IEnumerable<[K, V]> { }
  interface Set<T> extends IEnumerable<T> { }
  interface String extends IEnumerable<string> { }
  interface TypedArray extends IEnumerable<number> { }
}
class Enumerable<T>  implements IEnumerable<T> {
  readonly [Symbol.iterator]: IteratorFunction<T>
  readonly compare: (null | CompareFunction<T>)

  constructor (iterator: IteratorFunction<T>)
  constructor (iterator: IteratorFunction<T>, compare?: (null | CompareFunction<T>)) {
    this[Symbol.iterator] = iterator
    this.compare = compare
    }

    next(): IteratorResult<T> {
        return undefined;
    }
}

const C: IEnumerableConstructor = Enumerable;

type A = { a: string };
let a: A[];

const c = new C(a.values); // inferred as const c: IEnumerable<A>