javascript 使用类型脚本重载函数返回类型

cclgggtu  于 2023-02-15  发布在  Java
关注(0)|答案(1)|浏览(113)

我正在尝试构建一个通用的"req"函数,该函数接受URL路径(字符串)和对象(GET/POST参数)作为参数,并返回具有适当推断类型的结果。
这将是我的函数获取其类型定义的接口:

interface ValidQueries{
    books: (q: {
        limit?: number;
        category?: string;
    }) => Book[];

    authors: (q: {
        name?: string;
    }) => Author[];
}

并尝试编写函数:

const req = <K extends keyof ValidQueries>(path: string, params: (Parameters<ValidQueries[K]>[0])) => {
    return useQuery([path, params], ({ queryKey }) => {
        const [, params] = queryKey;
        return httpRequest(path, params) as Promise<ReturnType<ValidQueries[K]>>;
    });
};

示例:
req("books", { limit: 10 });-〉返回类型应该显示为Book [],第二个arg应该显示为接口中匹配函数的"q"类型。
params类型定义似乎不正确。2我想从接口(q)的函数中获取第一个参数的类型。
返回类型Promise<ValidQueries[K]>可以工作,但它并不理想,因为我看到了所有可能的类型,比如Book[] | Author[],而不是如果我将"books"作为第一个参数传递时只看到Book[],或者如果我将"authors"作为第一个参数传递时只看到Author[] ...

ercv8c1e

ercv8c1e1#

最重要的是,当你使用泛型时,你需要有一些锚,TypeScript可以从中推断。在这个函数中,你使用path: string(所以任何字符串),而使用泛型K的唯一参数是params
正因为如此,当你调用req("books", { limit: 10 })时,为了计算泛型K,它会做类似Extract<ValidQueries[keyof ValidQueries], { limit: 10 }>的事情。为了解决这个问题,你可以使用K作为路径参数-path: K。这将有助于从ValidQueries中找到合适的方法。
它还应该解决Book[] | Author[]的问题,除非useQuery有不正确的类型(然后您可以将as …子句推到末尾,或者直接键入函数返回类型)。
此外,您可以使用像...params: Parameters<…>这样的rest参数,因此它将允许向下传递任意数量的ValidQueries[K]参数,还将把q:名称添加到IDE中的参数中,这正是您所期望的。
总结一下,你有这样的东西:

interface ValidQueries {
  books: (q: { limit?: number, category?: string }) => Book[];
  authors: (q: { name?: string }) => Author[];
}

const req = <K extends keyof ValidQueries, T extends ValidQueries[K]>(path: K, ...params: Parameters<T>) => {
  return useQuery([ path, params ], ({ queryKey }) => {
    const [ , params ] = queryKey;
    return httpRequest(path, params) as Promise<ReturnType<T>>;
  });
};

不过有一个小的调整,T类型在这里是自动创建的,作为一个别名,你可以使用完整的Parameters<ValidQueries[K]>形式(对于返回类型也是类似的)。

相关问题