I wondering how to correctly infer 2th and 3th template of my function
suppose a simple interface
interface ISome {
a: string;
b?: {
c: string;
};
}
The following works:
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
but I need to generalize the function to work by specify another type ( I don't want to pass an object instance to specify the type )
So, the following does not work:
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)
It seems that the 2nd and 3rd template arguments of the function don't infer from the first, but it should because when I directly specified the type as T = ISome
, it worked.
I'm not sure if there is some language keyword to make it work but the template should work exactly for that: specify an unknown type.
EDIT
Actually I found this way, but require extra coding I would avoid if possible
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");