사용 시 제네릭에 바인딩된 유형을 기반으로 다른 Typescript 함수 유형 서명 만들기

8611 단어 typescript
다른 무엇보다 이것을 메모하고 싶었습니다. 얼마 전에 나는 모든 API 클라이언트 기능에 대해 "한 가지 유형"을 만들 수 있는 방법을 알아내려고 시간을 보냈습니다. 약간의 고군분투 끝에 더 일반적인 것을 모두 가질 수는 없다고 생각했습니다. 음, 다른 유형의 기능입니다.
  • 일부 인수 없음
  • 일부는 리소스 ID
  • 만 사용합니다.
  • 일부는 요청 본문만 가져옴
  • 일부는 리소스 ID와 요청 본문을 모두 사용합니다.

  • ... 그리고 그들은 모두 같은 유형을 반환합니다 (물론) - 여기서는 실제로 중요하지 않습니다.

    마지막으로 TS에서 조건부 유형을 살펴보기로 했습니다. 나는 이 기능에 대해 알고 있었지만 실제로 "실제"코드 기반에서 사용하지 않았습니다. 나는 여전히 "벌거 벗은"유형과 그렇지 않은 것에 대해 머리를 숙여야하지만 기본적으로 다음과 같은 충분한 솔루션을 얻을 수있었습니다.

    export type ApiClientFn<TId, TReqBody, TResBody> = [TId, TReqBody] extends [
      undefined,
      undefined,
    ]
      ? () => ApiClientRes<TResBody>
      : [TId, TReqBody] extends [number, undefined]
      ? (id: number) => ApiClientRes<TResBody>
      : [TId, TReqBody] extends [undefined, TReqBody]
      ? (reqBody: TReqBody) => ApiClientRes<TResBody>
      : [TId, TReqBody] extends [number, TReqBody]
      ? (id: number, reqBody: TReqBody) => ApiClientRes<TResBody>
      : never;
    


    기본적으로 이제 extend을 사용하여 API 클라이언트 함수 유형의 다양한 변형을 생성할 수 있습니다. 여기에 3개의 인수를 전달하여 일반 유형을 바인딩합니다.

    const getOne: ApiClientFn<number, TReqBody, TResBody> = async (id) => { // …
    
    const getList: ApiClientFn<undefined, TReqBody, TResBody> = async () => { // …
    
    const create: ApiClientFn<undefined, TReqBody, TResBody> = async (reqBody) => { // …
    
    export const update: ApiClientFn<number, TReqBody, TResBody> = async (
      id,
      requestBody,
    ) => { // …
    


    내가 처음에 염두에 두었던 것이 아닙니다. 나는 처음에 "모든 API 클라이언트 기능"을 나타내는 하나의 유형을 갖도록 설정했습니다. 그래도 실제로 그 유형이 필요하지 않은 것으로 나타났습니다. 나는 그것을 ApiClientFn 함수에서 사용하려고 했습니다. 이 함수에서 게터 클라이언트 API 함수 중 하나를 가져와 "공통 워크플로"에서 사용하는 하나의 후크를 갖고 싶었습니다. 그래서 useQueryApiError 이 제대로 작동하고 특정 상태 코드 응답에서 로그인 페이지로 리디렉션하고 로그아웃(및 알림) 등을 수행합니다.

    알고 보니 "내가 가지고 있는 모든 API 클라이언트 함수"에 대한 유형이 필요하지 않았습니다.

    export type ApiFnWrapper<TResBody> = () => ApiClientRes<TResBody>;
    


    … 그리고 실제 API 클라이언트 함수가 인수를 사용하는 경우 아래의 react-queryuseQuery에 있는 것처럼 항상 닫힐 수 있습니다.

      export const useSomeResource = (id: number, queryKey: string = 'queryId') => {
      const { data, ...rest } = useQueryApi(() => getOne(id), {
        queryKey,
      });
    
      return {
        data: data?.data,
        ...rest,
      };
    };
    



    어쨌든 id "공장 유형 기능"또는 기술 용어가 무엇이든 다음을 수행할 수 있습니다.
  • 한 곳에서 내 API 클라이언트 기능의 모든 유형 서명 보기
  • 다양한 변형에 대해 어리석은 이름을 계속 사용할 필요가 없습니다. () => getOne(id)

  • ... 그리고 그것은 나에게 승리처럼 보입니다.

    좋은 웹페이지 즐겨찾기