typescript - 推断通用的“this”类型
问题描述
继这个问题之后,我现在尝试使用扩展接口类型的显式this 参数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
})
}
但是, usingmakeArrayedAll
不起作用 -this
被推断为 type 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
解决方案
对我来说,这看起来像是您希望arrayedReturnFunctions
分配输出的变量的类型makeArrayedAll()
将为输入提供足够的上下文类型,以便推断makeArrayedAll()
输入方法的上下文......但它没有发生。this
在这种情况下,上下文推理不会发生,我并不感到惊讶,但我对究竟为什么或如何强制它发生没有很好的答案。
现在我唯一的建议是注意类型推断往往在“向前”方向上工作得更好。也就是说,泛型函数的类型参数更容易从该函数的输入推断出来,而不是从函数的预期输出类型推断出来。如果失败,您总是可以手动指定泛型类型参数。
这是手动指定模型类型参数并让编译器使用currying推断其余部分的一种方法:
const makeArrayedAllFor = <M extends IModel>() => <AS extends object>(
fs: SingleArgFunctionObject<M, AS>) => makeArrayedAll(fs);
const arrayedReturnFunctions3: ArrayedReturnFunctions = makeArrayedAllFor<MyModel>()({
foo(x) {
return x + this.state.x;
}
})
const arrayedReturnFunctions4 = makeArrayedAllFor<MyModel>()(singleArgFunctions);
这现在有效,虽然它很麻烦。这是我目前能想到的最好的;也许有人有其他想法?哦,好吧,祝你好运!
推荐阅读
- pandas - pd.read_csv 无法加载客户评论数据
- node.js - Socket.emit 带来多个值
- javascript - Angular JS 1.1:使用带有 ng-include 的共享 Angular 模块
- json - 从 for 循环插入文档时获取 XDMP-CONFLICTINGUPDATES
- jquery - jQuery更改格式不将格式更改为规定格式
- android - 使用来自 API 调用 Android 的数据显示 BottomSheet
- mobile - 使用 Bitrise 打开 STF 会导致无法获取设备序列号,错误:
- python - 列表中某个值范围内的最小值
- python - 如何获取对 discord.py 中的消息做出反应的成员列表?
- database - 使用带有 LiipFunctionalTestBundle 和 Postgresql 的夹具