
ts 中根据第一个参数约束第二个参数并推断结果的函数
在 typescript 中,你想要实现一个能够根据第一个参数约束第二个参数,并推断出最终结果的函数。例如,你希望该函数可以合并路径和参数,根据路径约束所传的参数,最终拼接路径和参数得到最终的字符串。
最初的实现使用了泛型和条件类型,但存在一些问题。本文将介绍一个改进的实现,以满足你的要求,使函数能够直接推断出正确的结果。
改进的实现
我们对 buildstringwithparams 函数进行了一些修改,如下所示:
type path2params = {
'/order/detail': { orderid: string };
'/product/list': { type: string; pagesize: string; pageno: string };
};
type buildquerystring> = {
[k in keyof tparams]: `${extract}=${tparams[k]}`;
}[keyof tparams];
type finalbuildquerystring> = joinwithampersand<
uniontotuple>
>;
type joinwithampersand = t extends [
infer first extends string,
...infer rest extends string[]
]
? rest extends []
? first
: `${first}&${joinwithampersand}`
: "";
type fullurl<
tpath extends string,
tparams extends record
> = `${tpath}${tparams extends record ? `?${finalbuildquerystring}` : ""}`;
function buildstringwithparams(
path: tpath,
params: tparams
): fullurl {
// ... 省略实现
} 关键变化
主要的改进是引入了 finalbuildquerystring 类型,它使用 joinwithampersand 将查询字符串中的键值对连接起来,并使用 & 符号分隔它们。
此外,我们使用了 uniontotuple 将 buildquerystring 的联合类型转换为元组,然后将它们传递给 joinwithampersand。这确保了查询字符串中的键值对始终按照正确的顺序出现。
使用改进的实现
使用改进的实现,你可以像这样推断出最终结果:
const orderUrl = buildStringWithParams('/order/detail', orderParams); // 推断为 "/order/detail?orderId=123"
const productListUrl = buildStringWithParams('/product/list', productListParams); // 推断为 "/product/list?type=electronics&pageSize=10&pageNo=1"此实现可以保证在没有运行时开销的情况下推断出类型安全且准确的结果,从而满足你的要求。










