代码之家  ›  专栏  ›  技术社区  ›  Andy

如何将Typescript Generic应用于以下API获取程序

  •  0
  • Andy  · 技术社区  · 4 年前

    我创建了一个相当简单的函数来环绕fetch。我试图弄清楚的是如何使用TS泛型在返回中为“data”设置类型。

    const apiFetchData = async (
        url: string,
        options = {},
    ): Promise<FetchResponse> => {
        try {
            const res = await fetch(url, options);
            const data = (await res.json()) || null;
            const statusCode = res.status;
    
            return {
                data,
                hasData: !!data,
                statusCode,
                error: (statusCode !== 200 && true) || false,
                errorType: (statusCode !== 200 && 'api') || null,
            };
        } catch (error) {
            return {
                data: {
                    error: error.message,
                },
                hasData: false,
                statusCode: 500,
                error: true,
                errorType: 'application',
            };
        }
    };
    

    FetchResponse类型看起来像这样:

    type FetchResponse = {
      data: {
        [key: string]: {};
        error?: string;
      };
      hasData: boolean;
      statusCode: number;
      error: boolean | null;
      errorType?: 'api' | 'application' | null;
    };
    

    如果我知道我的API将返回以下内容:

    type User = {
      name: string;
      email: string;
    }
    

    然后,我希望我的FetchResponse是:

    type FetchResponse = {
      data: User;
      hasData: boolean;
      statusCode: number;
      error: boolean | null;
      errorType?: 'api' | 'application' | null;
    };
    

    这样我就可以做这样的事情:

    const response = await apiFetchData('URL');
    console.log('User name is', response.data.name);
    

    目前我做了这样的事情,这很有效,但看起来很长

    type FetchWithUserType = FetchResponse & {
        data: {
            error?: string;
            user?: User;
        };
    };
    

    然后:

    const response: FetchWithUserType = await apiFetchData('URL');
    console.log('User name is', response.data.name);
    

    如果仿制药不是前进的方向,有人能帮我把它做得更好吗?这样我就可以做我想要的了。本质上,问题在于我希望我的VSCode智能感知知道返回的数据中有什么。Vs.是一个并且必须在代码之间不断切换。

    0 回复  |  直到 4 年前
        1
  •  1
  •   sam256    4 年前

    当你说“我知道我的API会返回以下内容”时,你的意思有点不清楚。我想你不是说你的API会 总是 返回该值,否则您将刚刚定义FetchResponse以包含该数据。

    如果你的意思是,你知道API将返回某个URL的结构,你可以用泛型处理如下:

    async function apiFetchData<T extends {[key:string]: any}>(
    // function params omitted
    ):Promise<FetchResponse<T>> => {
    // function code omitted
    }
    

    然后将FetchResponse定义为

    type FetchResponse<S> = {
       data: <S>
       // rest of the type
    }
    

    基本上,您使用泛型告诉TS您知道数据的形式,以便它可以将其插入FetchResponse类型。

    如果你的意思是你不知道API会提前返回什么,但它可能会以User格式返回数据,那么你需要使用类型保护。但我认为你可能指的是前面的例子。