В качестве примера рассмотрим следующий базовый класс:
abstract class Base<T> {
public changeGeneric = (): Base<string> => {
// do something so no matter what "T" currently is it will change to "string"
return this as Base<string>
}
}
Это работает, как и ожидалось. Но это усложняется при расширении Base
:
class Extended<T> extends Base<T> {
//...
public additionalFunc = () => {/*...*/}
}
const extended = new Extended<number>();
extended.changeGeneric().additionalFunc(); // this line results in and error
После вызова extended.changeGeneric()
тип должен быть Extended<string>
, но в этом случае это (вроде бы) очевидно Base<string>
. Поскольку additionalFunc
не существует для типа Base<string>
, возникает ошибка.
Детская площадка
Вопрос
Можно ли вернуть this
с различными типами c generic в зависимости от текущего класса, из которого выполняется функция? Если нет, есть ли обходные пути?
Это действительно простой пример (например, Base
может иметь больше обобщенных c типов), но я надеюсь, что это показывает проблему.
Подробнее о фактическом контексте
В моем конкретном случае я пытаюсь реализовать свободный API для проверки формы. Если я действительно сломаю это, это будет выглядеть так:
abstract class BaseConfig<T extends object, Errors = unknown> {
protected validator: (values: T) => Errors = () => undefined as any;
constructor(public initalValues: T){}
public withValidation = <Validator extends (values: T ) => any>(validator: Validator) => {
this.validator = validator ;
return this as any as BaseConfig<T, ReturnType<Validator>>
}
}
class SpecialConfig<T extends object, Errors = unknown> extends BaseConfig<T, Errors>{
protected specialConfigEnabled = false;
public enableSpecialConfig = () => {
this.specialConfigEnabled = true;
return this;
}
}
interface Coordinate {
x: number;
y: number;
}
const specialConfig = new SpecialConfig<Coordinate>({x: 0, y: 0})
// should somehow return SpecialConfig<Coordinate, boolean>, but returns BaseConfig<Coordinate, boolean> instead
.withValidation(({x, y}) => x > y? false : true)
// should not be an error
.enableSpecialConfig();
Детская площадка