Typescript泛型中对接口成员的约束

Evg*_*eny 3 generics interface constraints typescript

我有一个方法,它可以接受任何对象,只要它的所有字段都是字符串或数字

我做了这个,非常适合鸭子打字

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("/");
}
Run Code Online (Sandbox Code Playgroud)

并打电话

interpolateParams("/api/:method/:value", {method: "abc", value: 10});
Run Code Online (Sandbox Code Playgroud)

现在,我想interpolateParams接受route的任何接口params

interpolateParams<IABCParams>("/api/:method/:value", {method: "abc", value: 10});
Run Code Online (Sandbox Code Playgroud)

问题是它仍然应该匹配所有字符串或数字字段的约束

有没有一种方法可以在给定接口的所有字段上将泛型约束指定为特定类型?

我尝试过

static interpolateParams<T extends {[key: string] : string | number}>(
    route: string, 
    params: T) : string {
Run Code Online (Sandbox Code Playgroud)

显然得到了这个

类型'IABCParams'不满足约束'{{[key:string]:string | 数; }'。

类型“ IABCParams”中缺少索引签名。

谢谢

Mat*_*hen 5

T的约束可以引用T(有一些约束),因此您可以使用映射类型来生成与以下字段具有相同字段的约束T

function interpolateParams<T extends {[P in keyof T] : string | number}>(
    route: string, 
    params: T) : string { /*...*/ }
Run Code Online (Sandbox Code Playgroud)

请注意,使用圆形类型参数约束的欺骗有时可能会导致问题,尽管这种情况可能是可以的。