Как я упоминал в комментариях, это не может быть выражено в системе типов TypeScript (во всяком случае, с TS3.1).TypeScript очень ограничен в своей способности представлять так называемые типы с более высоким родом .
Во-первых, вы хотите сказать, что все подклассы MyFunction<T>
должны быть общими в T
.То есть вам не нужно расширять тип MyFunction<T>
, а конструктор типа T ⇒ MyFunction<T>
, который преобразует тип T
в MyFunction<T>
.Но вы не можете этого сделать, потому что нет общего способа ссылаться на конструкторы типов в TypeScript (Microsoft / TypeScript # 1213) .
Далее, при условии, что вы можете расширить T ⇒ MyFunction<T>
ине MyFunction<T>
, вам понадобится полиморфный * TypeScript this
, чтобы учесть это, так что this
также является конструктором типа, а this<X>
- конкретным типом.И вы тоже не можете этого сделать (Microsoft / TypeScript # 5845) .
Поскольку Microsoft / TypeScript # 1213 по-прежнему остается открытой проблемой и находится в состоянии «требуется помощь», существуетнекоторые надеются, что в конечном итоге вы сможете сделать это.Но я не задерживал дыхание.Если вы посмотрите на эту проблему, вы увидите некоторые обходные пути, которые используют некоторые люди, но, на мой взгляд, они слишком громоздки, чтобы я рекомендовал.
Вы можете попробовать что-то вроде:
composeU<U>(g: (t: T) => U): MyFunction<U> {
return new (this.constructor as any)((n: number) =>
g(this.f(n));
);
}
но вам нужно будет явно сузить определения для каждого подкласса, если вы хотите охватить дух полиморфизма this
:
class MyFancyFunction<T> extends MyFunction<T> { }
interface MyFancyFunction<T> {
composeU<U>(g: (t: T) => U): MyFancyFunction<U>;
}
В приведенном выше описании мы используем объявление слияния для суженияcomposeU
метод MyFancyFunction
.
В любом случае, надеюсь, что это поможет.Удачи!