我想知道如何正确推断函数的第二和第三模板
假设一个简单的界面
interface ISome {
a: string;
b?: {
c: string;
};
}
关注作品
function pathBuilder<
K1 extends keyof ISome,
K2 extends keyof NonNullable<ISome[K1]>>(p: K1, p2?: K2) {
let res = String(p);
if (p2) { res += "." + p2; }
return res;
}
const pathTest = pathBuilder("b", "c"); // ---> "b.c" and intellisense works on parameters
但是我需要通过指定其他类型来概括该功能,以使其工作(我不想通过对象实例来指定类型)
所以,以下操作无效
function pathBuilder<
T,
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>>(p: K1, p2?: K2) {
let res = String(p);
if (p2) { res += "." + p2; }
return res;
}
const pathTest = pathBuilder<ISome>("b", "c"); // ERROR: Expected 3 type arguments, but got 1.ts(2558)
似乎该函数的第2个和第3个模板参数不能从第一个参数推断出,但是应该这样做,因为在第一种情况下,当我直接指定类型T = ISome时,它就起作用了。
我不确定是否可以使用某种语言关键字来使它起作用,但是模板应完全适合该语言:指定未知类型。
编辑
实际上我是用这种方法找到的,但是需要额外的编码,如果可能的话,我会避免
function pathBuilder<T>() {
return <
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>>(p: K1, p2?: K2) => {
let res = String(p);
if (p2) { res += "." + p2; }
return res;
};
}
const pathTest = pathBuilder<ISome>()("b", "c");
答案 0 :(得分:3)
从TS3.4开始,没有partial type parameter inference。您要么让编译器尝试推断所有类型参数,要么指定所有类型参数。 (嗯,有default type parameters,但这并不能满足您的需求:您想推断所遗漏的类型参数,而不分配 default 输入他们)。已有several个提案address,但是到目前为止none have met with full approval。
因此,目前只有解决方法。我可以想到的两个是使用虚拟函数参数还是使用currying。
虚拟参数版本:
function pathBuilderDummy<
T,
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>>(dummy: T, p: K1, p2?: K2) {
let res = String(p);
if (p2) { res += "." + p2; }
return res;
}
const pathDummyTest = pathBuilderDummy(null! as ISome, "b", "c");
在这里,我们正在执行您所说的您不想做的事情...传入类型T
的参数。但是,由于它只是一个伪参数,并且在运行时不使用,因此仅取决于类型系统的想法。您传入的值的实际类型无关紧要。因此,您只需将其传递给null
并使用type assertion来选择T
。
咖喱函数解决方案:
const pathBuilderCurry =
<T>() => <
K1 extends keyof T,
K2 extends keyof NonNullable<T[K1]>>(p: K1, p2?: K2) => {
let res = String(p);
if (p2) { res += "." + p2; }
return res;
}
const pathCurryTest = pathBuilderCurry<ISome>()("b", "c")
这里您要返回的函数将返回另一个函数。第一个函数不带值参数,但可以带一个您要指定的类型参数。然后,它返回一个指定了T
但推断出其他类型参数的函数。
这两种解决方案都不完美,但是它们是我们目前能做到的最好的解决方案。希望能有所帮助;祝你好运!