Исходя из этого вопроса, я сейчас пытаюсь создать функции с явным этим параметром типа расширяющего интерфейс IModel
:
// interface for Model class
interface IModel {
state: {}
}
// based on answer to this question https://stackoverflow.com/q/59895071/374328
// now functions will be bound to model instance, so need to specify 'this' parameter as Model
type SingleArgFunction<Model extends IModel, A> = (this: Model, x: A) => A;
type ArrayedReturnFunction<Model extends IModel, A> = (this: Model, x: A) => A[];
type SingleArgFunctionObject<Model extends IModel, AS extends object> = {
[K in keyof AS]: SingleArgFunction<Model, AS[K]>
}
type ArrayedReturnFunctionObject<Model extends IModel, AS extends object> = {
[K in keyof AS]: ArrayedReturnFunction<Model, AS[K]>
}
function makeArrayed<Model extends IModel, A>(f: SingleArgFunction<Model, A>): ArrayedReturnFunction<Model, A> {
return function (x) {
return [f.call(this, x)];
}
}
function makeArrayedAll<Model extends IModel, AS extends object>(
fs: SingleArgFunctionObject<Model, AS>
): ArrayedReturnFunctionObject<Model, AS> {
const result = {} as ArrayedReturnFunctionObject<Model, AS>;
(Object.keys(fs) as (keyof AS)[]).forEach(function<K extends keyof AS>(key: K) {
result[key] = makeArrayed(fs[key]);
})
return result;
}
Пример определения модели и типа:
interface MyModel extends IModel {
state: {
x: number;
}
}
interface SingleArgFunctions {
foo: SingleArgFunction<MyModel, number>
}
interface ArrayedReturnFunctions {
foo: ArrayedReturnFunction<MyModel, number>;
}
Создание объекта ArrayedReturnFunctions
напрямую в порядке, с this
выводится как тип MyModel
:
const arrayedReturnFunctions1: ArrayedReturnFunctions = {
foo(x) {
return [x + this.state.x]; // ok
}
}
В качестве альтернативы создание объекта путем применения makeArrayed
к одной функции также нормально:
const arrayedReturnFunctions2: ArrayedReturnFunctions = {
foo: makeArrayed(function (x) {
return x + this.state.x; // ok
})
}
Однако использование makeArrayedAll
не работает - this
выводится как тип IModel
:
const arrayedReturnFunctions3: ArrayedReturnFunctions = makeArrayedAll({
foo(x) {
return x + this.state.x; // error - property x does not exist on type {}
}
})
Даже создание объекта типа SingleArgFunctions
и передача его в makeArrayedAll
не работает:
const singleArgFunctions: SingleArgFunctions = {
foo(x) {
return this.state.x + x;
}
}
const arrayedReturnFunctions4 = makeArrayedAll(singleArgFunctions); // error - IModel is not assignable to type MyModel
Почему тип Model
не выводится как MyModel
, когда Использование makeArrayedAll
?
Детская площадка