StudyForYou / ouahhan-typescript-with-react

우아한 타입스크립트 with 리액트 스터디 레포 🧵
4 stars 0 forks source link

#9 [3장_3] 함수의 제네릭과 호출 시그니처의 제네릭을 설명해주세요! #21

Closed hyeyoonS closed 3 months ago

hyeyoonS commented 3 months ago

❓문제

함수의 제네릭과 호출 시그니처의 제네릭을 설명해주세요!

🎯답변 요약

🎯답변

함수의 제네릭

// 지피티가 알려줌..~

// 제네릭을 사용하여 다양한 타입의 매개변수와 반환 값 다루기
function processValue<T>(value: T): T {
    if (typeof value === 'number') {
        // 만약 입력된 값이 숫자일 경우에는 2를 곱한 값을 반환
        return value * 2;
    } else if (typeof value === 'string') {
        // 만약 입력된 값이 문자열일 경우에는 역순으로 변환하여 반환
        return value.split('').reverse().join('');
    } else {
        // 기타 다른 타입의 경우 입력된 값을 그대로 반환
        return value;
    }
}

// 숫자 입력
const numberResult = processValue(5);
console.log(numberResult); // 10

// 문자열 입력
const stringResult = processValue("hello");
console.log(stringResult); // "olleh"

// 다른 타입 입력
const otherResult = processValue(true);
console.log(otherResult); // true (기존 값 그대로 반환)

호출 시그니처의 제네릭

type LogFn = (text: string) => void;
let log: LogFn = (text) => console.log(text);
// 제네릭 함수 타입 시그니처 선언
type ProcessFunction<T> = (value: T) => T;

// 제네릭 함수 타입을 가진 변수 정의
let processNumber: ProcessFunction<number>; // 1. 이렇게 number로 지정하거나
let processString: ProcessFunction<string>; // 2. 이렇게 string으로 지정할 수 있다~

// 숫자를 받아서 2를 곱한 값을 반환하는 함수
processNumber = (value) => value * 2;

// 문자열을 받아서 역순으로 변환하여 반환하는 함수
processString = (value) => value.split('').reverse().join('');

// 함수 호출
const numberResult = processNumber(5);
console.log(numberResult); // 10

const stringResult = processString("hello");
console.log(stringResult); // "olleh"

📝 FYI) 호출 시그니처에 대해서 사실 엄밀하게 말하면 함수 타입 표현식과 다른 표현 방식인 것 같습니다. 호출 시그니처도 함수 타입 표현식처럼 함수의 타입을 정의하는 방식이지만, 함수를 객체를 정의하듯 타입을 정의하는 방식을 뜻하는 것으로 아래 참고 문서에 나와 있습니다.

// 'arrow' 방식이 아닌 '프로피터: 값' 방식으로 함수 타입을 정의
type Operation2 = {
  (a: number, b: number): number;
};
drizzle96 commented 3 months ago

함수 타입과 함수 타입 표현식은 둘 다 제네릭을 사용하여 매개변수와 리턴 값에 다양한 타입이 들어오도록 만들 수 있습니다.

예를 들어 a, b를 받아 순서를 바꾼 배열인 [b, a]를 리턴하는 아래가 함수가 있을 때

const swap = (a, b) => [b, a]

swap 함수에 제네릭을 적용하면 다음과 같습니다.

const swap = <T, U>(a: T, b: U): [U, T] => [b, a]
swap(1, 'a')

함수 타입 표현식은 함수의 매개변수, 리턴 값 타입을 미리 지정하는 방식입니다. 예를 들어 Calculator 컴포넌트가 props로 함수를 받는다면 CalculatorProps에 함수를 기재할 때 함수 타입 표현식으로 함수의 매개변수, 리턴 값 타입을 미리 지정할 수 있습니다. 이 때 CalculatorProps을 제네릭으로 하여 함수 타입 표현식에 제네릭 변수를 적용할 수 있습니다.

interface CalculatorProps<T, U> {
  add: (a: T, b: T) => T
}

📝 FYI) 호출 시그니처에 대해서 사실 엄밀하게 말하면 함수 타입 표현식과 다른 표현 방식인 것 같습니다. 호출 시그니처도 함수 타입 표현식처럼 함수의 타입을 정의하는 방식이지만, 함수를 객체를 정의하듯 타입을 정의하는 방식을 뜻하는 것으로 아래 참고 문서에 나와 있습니다.

// 'arrow' 방식이 아닌 '프로피터: 값' 방식으로 함수 타입을 정의
type Operation2 = {
  (a: number, b: number): number;
};

참고 문서 1) 한 입 크기로 잘라먹는 TS 참고 문서 2) TS 공식 문서

hyeyoonS commented 3 months ago

함수의 제네릭

// 지피티가 알려줌..~

// 제네릭을 사용하여 다양한 타입의 매개변수와 반환 값 다루기
function processValue<T>(value: T): T {
    if (typeof value === 'number') {
        // 만약 입력된 값이 숫자일 경우에는 2를 곱한 값을 반환
        return value * 2;
    } else if (typeof value === 'string') {
        // 만약 입력된 값이 문자열일 경우에는 역순으로 변환하여 반환
        return value.split('').reverse().join('');
    } else {
        // 기타 다른 타입의 경우 입력된 값을 그대로 반환
        return value;
    }
}

// 숫자 입력
const numberResult = processValue(5);
console.log(numberResult); // 10

// 문자열 입력
const stringResult = processValue("hello");
console.log(stringResult); // "olleh"

// 다른 타입 입력
const otherResult = processValue(true);
console.log(otherResult); // true (기존 값 그대로 반환)

호출 시그니처의 제네릭

type LogFn = (text: string) => void;
let log: LogFn = (text) => console.log(text);
// 제네릭 함수 타입 시그니처 선언
type ProcessFunction<T> = (value: T) => T;

// 제네릭 함수 타입을 가진 변수 정의
let processNumber: ProcessFunction<number>; // 1. 이렇게 number로 지정하거나
let processString: ProcessFunction<string>; // 2. 이렇게 string으로 지정할 수 있다~

// 숫자를 받아서 2를 곱한 값을 반환하는 함수
processNumber = (value) => value * 2;

// 문자열을 받아서 역순으로 변환하여 반환하는 함수
processString = (value) => value.split('').reverse().join('');

// 함수 호출
const numberResult = processNumber(5);
console.log(numberResult); // 10

const stringResult = processString("hello");
console.log(stringResult); // "olleh"