我想在其自身的约束中使用泛型类型参数。打字稿根本有可能吗?
我的代码在这里:
hm <- pheatmap(test, silent = TRUE)
hm$gtable$grobs[[5]]$gp$col <- rep(c("black", "red"), each = 10)
leg <- legendGrob(c("Exp1", "Exp2"), nrow = 2, pch = 15, gp = gpar(fontsize = 10, col = c("black", "red")))
hm2 <- arrangeGrob(hm$gtable, leg, ncol = 2, widths = c(5,1))
grid.draw(hm2)
中
我正在尝试创建一个配置功能,以使用预定义的上下文执行一组功能。
我已经设法创建了一个简单的演示版本,但是现在我希望能够从另一个挂钩中调用挂钩。例如。我想将我的type Config<T> = {
context: T;
};
type Hooks<T> = {
hooks: T;
};
type FunctionWithThis<T> = (this: T, ...args: any[]) => any;
type RemoveThis<T extends Record<string, FunctionWithThis<any>>> = {
[P in keyof T]: T[P] extends (...a: infer A) => infer R ? (...a:A) => R: never
}
const configure = <TContext extends Object,
THooks extends Record<string, FunctionWithThis<TContext & THooks>>> // problem here
(config: Config<TContext> & Hooks<THooks>) => {
const result = {
get data() { return config.context; }
};
Object.entries(config.hooks).forEach((action) => {
(result as any)[action[0]] = (...args: any[]) => action[1].call(config.context as any, ...args);
});
return result as { data: TContext; } & RemoveThis<THooks>;
};
const engine = configure({
context: {
foo: 12
},
hooks: {
log() {
console.log(this.foo); // this.foo is typed correctly here but I don't have access to another hooks
},
test(str: string) {
}
}
});
挂钩配置为调用test
挂钩。
为了实现这一点,我试图将联合类型作为通用参数传递给“ FunctionWithThis”类型:
log
但是不幸的是,它并没有给我我想要的东西:我仍然对上下文有智能感知,这是因为我的钩子不可用。通用参数用作自身约束时,似乎解析为FunctionWithThis<TContext & THooks>
。
这是克服这个问题的方法吗?
实际上,我有更复杂的计划:我想为unknown
函数和回调添加一个通用参数,并且还希望能够从钩子调用回调,反之亦然。因此它看起来像这样:configure
,其中THooks extends Record<string, FunctionWithThis<TContext & THooks & TCallbacks>>>
是紧随TCallbacks
答案 0 :(得分:3)
仅泛型很难解决您的特定问题。幸运的是,TypeScript具有一个称为ThisType
的特殊魔术类型函数,该函数在microsoft/TypeScript#14141中实现,该函数允许指定对象文字方法的this
上下文。
我希望您输入的代码是这样的:
type ConfigwithHooks<C, H> = {
context: C;
hooks: H & ThisType<C & H>; // Type of 'this' in hooks is C & H
};
const configure = <C, H>(config: ConfigwithHooks<C, H>) => {
const result = {
get data() { return config.context; }
};
Object.entries(config.hooks).forEach((action) => {
(result as any)[action[0]] = (...args: any[]) => action[1].call(config.context as any, ...args);
});
return result as { data: C } & H;
};
我认为这可以按照您想要的方式工作:
const engine = configure({
context: {
foo: 12
},
hooks: {
log() {
console.log(this.foo);
this.test("hello");
},
test(str: string) {
this.foo - 5;
}
}
});
/* const engine: {
data: {
foo: number;
};
} & {
log(): void;
test(str: string): void;
} */
const data = engine.data;
engine.log();
我还没有研究如何实施更复杂的计划,但是我想确保您对所提出的问题中的代码有所了解。