Javascript 如何重写不提供与签名匹配的泛型构造函数的定义
我正在编写一个库来实现JavaScript中iterable类型的延迟计算查询。我知道已经有可用的选项可以实现这一点,但我的选择是采用完全不同的方法来公开扩展方法 我在处理一个特殊的设计挑战时遇到了困难,我想知道是否有一些我没有想到的解决问题的方法 我的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
可枚举
类定义及其接口以及一些帮助程序如下所示:
// 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规范扩展的类(但是TypeScriptlib.*.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>