说我在模块src/Container
中有以下接口
export abstract class Container<T> implements Iterable<T> {
public abstract [Symbol.iterator](): IterableIterator<T>
}
现在我想从另一个文件src/extensions/transformSomething
扩展该类
import { Container } from '../Container'
declare module '../Enumerable' {
interface Container<T> {
transformSomething<TOut>(this: Container<T>, selector: (x : T) => TOut) : Container<TOut>
}
}
然后我定义此扩展功能的实现
function transformSomething<T, TOut>(
this: Container<T>,
selector: (x : T) => TOut
): Container<TOut> {
//...
const returnValue:SomeContainerType<TOut> = //...
return returnValue
}
我现在可以轻松地将其附加到Container<T>
Container.prototype.transformSomething = transformSomething
获奖。
现在,说我已经有一个采用以下形式的不同,功能更丰富,原型较少的实现:
(...args: any[]) => (src: any) => any
例如:
export const transformSomethingF = <T, TOut>(selector: (x : T) => TOut) => (src: Container<T>): Container<TOut> => {
//...
const returnValue:SomeContainerType<TOut> = //...
return returnValue
}
我可以编写一个将其转换为基于this
的函数的方法:
export const convertForPrototype =
<TIn, TOut, U extends any[], T extends (...args: U) => (src: TIn) => TOut>
(func: T): (this: TIn, ...args: U) => TOut => {
return function (this: TIn, ...args: U) {
return func(...args)(this);
};
};
现在,将我们的transformSomethingF
转换为可在原型中运行的函数非常简单:
Enumerable.prototype.select = convertForPrototype(select)
那么,我们可以对上面的接口扩展做同样的事情吗?我们可以改变
import { Container } from '../Container'
declare module '../Enumerable' {
interface Container<T> {
transformSomething<TOut>(this: Container<T>, selector: (x : T) => TOut) : Container<TOut>
}
}
进入
import { Container } from '../Container'
declare module '../Enumerable' {
interface Container<T> {
transformSomething: PrototypeRepresentation<typeof transformSomethingF>
}
}
???
我们可以通过定义以下类型来做到这一点:
export type PrototypeRepresentation<TSrc,T extends (...args: any[]) => (src: any) => any> =
T extends (...args: infer P) => (src: TSrc) => infer TOut ?
(this: TSrc, ...arg: P) => TOut : never;
但是当我尝试这样做时,尝试实际使用Container.transformSomething
const someContainer : Container<number> = //...
const result = someContainer.transformSomething(x => x * 2)
我看到以下问题:
(参数)x:任意
无法调用类型缺少调用签名的表达式。类型“从不”没有兼容的呼叫签名。ts(2349)
参数'x'隐式具有'any'类型。ts(7006)
是否有办法使它正常工作?