【发布时间】:2020-01-24 18:41:28
【问题描述】:
假设我想编写一个函数,它接受某种类型 T 的对象和另一个值,该类型 P 应该以某种方式受 T 限制,例如 P 应该是 T 的键数组。
我可以很容易地写出来:
function bar<T, P extends keyof T>(obj: T, p: P[]) {
// use p to index obj somehow
return obj;
}
bar({ a: 1, b: 'foo' }, ['a']); // Ok
bar({ a: 1, b: 'foo' }, ['a', 'b']); // Ok
bar({ a: 1, b: 'foo' }, ['a', 'b', 'c']); // Error: 'c' is not valid key
想象一下,然后我想将该函数用作高阶方法的参数,它应该与第二个参数 arg 一起接受它,然后用 this 和 arg 调用它:
class Indexed {
constructor(public a: number = 1) {}
public app<P>(f: (obj: this, arg: P) => this, arg: P) {
return f(this, arg);
}
}
const a = new Indexed().app(bar, ['a']); // Error, `Type 'string' is not assignable to type '"a" | "app"'.`
const a = new Indexed().app(bar, ['wtf']); // The same
如果我直接使用bar,一切都会按预期进行:
bar(new Indexed(), ['a']); // Ok
bar(new Indexed(), ['wtf']); // Err, as expected
问题是:如何编写app 使其接受/拒绝参数的方式与bar 相同?
请注意,一般我不知道 bar 先验的限制,所以我不能用与 bar 相同的界限来限制 P。
【问题讨论】:
标签: typescript types type-inference