typescript泛型中接口成员的约束
我有一个方法,它应该接受任何对象,只要它的所有字段都是字符串或数字 我做了这个,用duck打字效果很好typescript泛型中接口成员的约束,typescript,generics,interface,constraints,Typescript,Generics,Interface,Constraints,我有一个方法,它应该接受任何对象,只要它的所有字段都是字符串或数字 我做了这个,用duck打字效果很好 static interpolateParams( route: string, params: {[key: string] : string | number}) : string { const parts = route .split("/") .map(part => { const match
static interpolateParams(
route: string,
params: {[key: string] : string | number}) : string {
const parts = route
.split("/")
.map(part => {
const match = part.match(/:([a-zA-Z09]*)\??/);
if (match) {
if (!params[match[1]]) {
console.error("route argument was not provided", route, match[1]);
return part;
}
return params[match[1]];
}
else {
return part;
}
})
return "/" + parts.slice(1).join("/");
}
打电话
interpolateParams("/api/:method/:value", {method: "abc", value: 10});
现在我想制作插值图
,以接受路由参数
的任何接口
interpolateParams<IABCParams>("/api/:method/:value", {method: "abc", value: 10});
插值图(“/api/:method/:value”,{method:“abc”,value:10});
问题是,它仍然应该匹配字符串或数字的所有字段的约束
有没有办法将给定接口的所有字段上的泛型约束指定为特定类型
我试过了
static interpolateParams<T extends {[key: string] : string | number}>(
route: string,
params: T) : string {
静态插值图(
路线:字符串,
参数:T):字符串{
很明显,我得到了这个
类型“IABCParams”不满足约束“{[key:string]:string | number;}”
类型“IABCParams”中缺少索引签名
感谢如果你想要
插值图(“/api/:method/:value”,{method:“abc”,value:10});
来进行类型检查,你不能。这是因为你不能推断出任何关于“/api/:method/:value”
的信息来给你一个方法,值
签名
变通办法
编写采用方法
和值
的函数,并使用它为配置和使用提供动力
这就是我使用的策略
T
的约束可以引用T
(有一些限制),因此您可以使用映射类型生成与T
具有相同字段的约束:
function interpolateParams<T extends {[P in keyof T] : string | number}>(
route: string,
params: T) : string { /*...*/ }
函数插值图(
路线:字符串,
参数:T):字符串{/*…*/}
请注意,使用循环类型参数约束的技巧有时可能会导致问题,尽管这种情况可能不会有问题。这是最终版本,感谢Matt的提示
static interpolateParams(
route: string,
params: {[key: string] : string | number}) : string {
const parts = route
.split("/")
.map(part => {
const match = part.match(/:([a-zA-Z09]*)\??/);
if (match) {
if (!params[match[1]]) {
if (part.endsWith("?")) {
return null;
}
console.error("route argument was not provided", route, match[1]);
return part;
}
return params[match[1]];
}
else {
return part;
}
}).filter(p => p && p != "");
return "/" + parts.join("/");
}
static formatRoute<T extends {[P in keyof T] : string | number}>(
route: string,
params: T
) : string {
return interpolateParams(route, params);
}
静态插值图(
路线:字符串,
参数:{[key:string]:string | number}):string{
常数部分=路线
.拆分(“/”)
.map(部分=>{
常数匹配=零件匹配(/:([a-zA-Z09]*)\??/);
如果(匹配){
如果(!params[匹配[1]]){
if(带(“?”)的部分末尾){
返回null;
}
错误(“未提供路由参数”,路由,匹配[1]);
返回部分;
}
返回参数[匹配[1]];
}
否则{
返回部分;
}
}).filter(p=>p&&p!=“”);
返回“/”+零件。连接(“/”);
}
静态格式化路由(
路线:字符串,
参数:T
):字符串{
返回插值图(路线、参数);
}
我的猜测是:不,没有。我希望是错误的。@AndrewShepherd如果sems是可能的,请检查Matt的评论和我的最终版本thanksOk,该版本运行得不太好,但使用附加层似乎欺骗了解释器:)如您所述,中的错误如果(!params[match[1]])
line-没有索引器。所以我按照您的建议添加了另一个版本的interpolateRoute,并在内部调用bare interpolate(代码见下一步)
static interpolateParams(
route: string,
params: {[key: string] : string | number}) : string {
const parts = route
.split("/")
.map(part => {
const match = part.match(/:([a-zA-Z09]*)\??/);
if (match) {
if (!params[match[1]]) {
if (part.endsWith("?")) {
return null;
}
console.error("route argument was not provided", route, match[1]);
return part;
}
return params[match[1]];
}
else {
return part;
}
}).filter(p => p && p != "");
return "/" + parts.join("/");
}
static formatRoute<T extends {[P in keyof T] : string | number}>(
route: string,
params: T
) : string {
return interpolateParams(route, params);
}