journey-dev 2023. 12. 22. 16:09

https://www.typescriptlang.org/ko/docs/handbook/2/generics.html

 

단일 타입이 아닌, 다양한 타입을 동적으로 정의할 수 있음.

코드의 재사용성과 유연성 증가, 코드를 추상화된 형태로 작성할 수 있게 됨

1. 제네릭 함수

function identity<T>(arg: T): T {
  return arg;
}

let result1: number = identity<number>(42); // result1의 타입은 number  
let result1: number = identity(42); // 타입 추론 사용

let result2: string = identity<string>("hello");  // result2의 타입은 string
let result2: string = identity("hello");  // 타입 추론 사용
  • <T> 제네릭 타입 매개변수 : 꺽쇠를 변수명,함수명 앞에 쓰면 "타입 단언"이 된다.
  • (arg : T) : 함수의 매개변수는 T타입이여서, 어떤 타입의 인수라도 받을 수 있음
  • :T : 함수의 리턴값에 대한 타입 정의
  •  
function loggingIdentity<T>(arg: T[]): T[] {
  return arg;
}

let result1: number[] = loggingIdentity([1, 2, 3]); 
let result2: string[] = loggingIdentity(["a", "b", "c"]);

// 타입 추론 사용됨. 때문에 loggingIdentity<number[]>([1, 2, 3]); <- 불필요
  • <T> 제네릭 타입 매개변수 : <T>을 통해 어떤 타입의 배열을 받을지 동적으로 결정할 수 있음
  • (arg: T[]) :함수의 매개변수는 T타입이여서,배열의 원소들이 어떤 타입이라도 받을 수 있음
  • T[] :함수의 리턴값에 대한 타입 정의, 받은 타입과 동일한 타입의 배열을 반환함.

 

2. 함수를 값으로 쓰기

- 변수에 함수 할당할 때 유용 

- 함수 자체를 매개변수로 전달할 때 유용

 

myIdentity라는 변수에 identity 함수를 할당하는 코드
: myIdentity 변수는 identity 함수와 동일한 함수 타입을 갖게 됨.

function identity<T>(arg: T): T {
  return arg;
}

let myIdentity: <T>(arg: T) => T = identity;  // 일반 js라면, let myIdentity = identity함수

let result1: number = myIdentity(42);        // result1의 타입은 number
let result2: string = myIdentity("hello");   // result2의 타입은 string

 

3. 제네릭 인터페이스

interface Pair<K, V> {
    key: K;
    value: V;
}

// 문자열과 숫자를 담은 Pair 인스턴스
let keyValue: Pair<string, number> = { key: "age", value: 25 };
 
 // 문자열과 불린형을 담은 Pair 인스턴스
let keyValue: Pair<string, boolean> = { key: "admin", value: true };
  • Pair는 제네릭 인터페이스 : K,V을 타입 매개변수로 받아 동적으로 타입이 결정됨
  •  Pair<string , number> : Paire<K,V>에 타입 매개변수가 할당됨

 4. html요소의 기본 속성을 확장하기 위한 제네릭 

// 부모 컴포넌트 App.tsx
<AssetImage image={item.image} className="prods-img" />
 
// 자식 컴포넌트 AssetImage.tsx
import { HTMLProps } from "react";

interface AssetImageProps extends HTMLProps<HTMLImageElement> {
  image?: string;
}

function AssetImage({ image, ...props }: AssetImageProps) {
  return <img src={imageUrl} {...props} />;
}

export default AssetImage;

 

  • AssetImageProps 인터페이스가 HTMLImageElement 요소에 대한 모든 속성을 상속한 것임
    이미지 엘리먼트에 사용되는 모든 표준 HTML 속성을 AssetImageProps에서도 사용할 수 있게 됨

Promise<T>
: 제네릭을 어디에 붙여야 하는지 어떻게 앎? prmise에 제네릭을 붙여야 한다는걸 어떻게 파악?

export interface GetManyResponse<T> {
  docs: T[];
  include?: any;
  limit: number;
  totalDocs: number;
}

export const useGetManyProduct = (prodQuery: ProductQueryParams) => {
  return useQuery({
    placeholderData: keepPreviousData, // https://tanstack.com/query/v5/docs/react/guides/paginated-queries <- layout shifting이 일어나지 않아, 레이아웃이 깨지지 않는다.
    // [제네릭] 2
    queryFn: (): Promise<GetManyResponse<Product>> => {
      return axiosInstance({
        method: "get",
        params: prodQuery,
        url: `/product`
      }).then((res) => res.data);
    },
    queryKey: ProductQuery.getMany(prodQuery) // ['all','getMany',{sort:price, title[match] :'Women'}]
    // refetchOnWindowFocus: isRefecth, // 탭을 나갔다가 다시 탭 눌렀을때, stale됐으면 자동으로 refetch되는 기능
  });
};

 


https://feel5ny.github.io/2018/12/09/Typescript_14/