TIL 22-06-08

thisisyjin·2022년 6월 15일
0

TIL 📝

목록 보기
62/113

TypeScript

🙋‍♂️ Ref Lecture


Call Signature

function add (a, b) { // warning - 타입 지정
  return a + b
}

함수 인자는 기본적으로 any 타입이라, 타입을 지정하는 것을 권장함.

const sub = (a: number, b: number): number => a - b;


-> 이것이 바로 함수의 Call Signature 이다.

  • type 키워드로 함수의 콜 시그니처를 선언한 후, 사용 가능.
type Add = (a:number, b:number) => number;

const add: Add = (a, b) => a + b;

Overloading

  • 오버로딩
  • function overloading (또는 method overloading)

overloading은 함수가 서로다른 여러개의 call signiture을 가질 때 발생함.

함수의 콜 시그니처를 아래와 같이 작성할수도 있음.

type Add = {
  (a: number, b: number) : number
}

만약, 여러개의 call signiture이 있다면?

type Add = {
  (a: number, b: number) : number
  (a: number, b: string) : number
}

const add: Add = (a, b) => a + b // a: number 인데, b: string | number 임.
// number과 string은 더해서 number이 될 수 없으므로 에러가 발생함.

위와 같이 call signiture가 여러개라 혼란이 올 수 있는 상황에서는
if문으로 분기를 해줘야 한다.

const add: Add = (a, b) => {
  if(typeof b === 'string') return a
  return a + b
}

BUT. 위와 같은 경우는 아주 안좋은 경우임.

같은 함수에서 인자로 string이 들어갈수도, 객체가 들어갈수도 있게 하려면?
-> 예시❗️ Next.js의 Router.push 함수

Router.push('/home');   // string을 전달해줌
Router.push({     // object를 전달해줌
  path: '/home',
  state: 1
});

위와 같은 경우에는 타입을 아래처럼 설정하면 됨.

type Config = {
  path: string
  state: object
}

type Push = {
  (path: string): void
  (config:  Config): void
}

const push: Push = (config) => {
  if(typeof config === 'string') { 
    console.log(config);
    //  문자열인 경우
  } else {
    console.log(config.path);
  //  객체인 경우
  }
}

Add 함수 응용

  • 파라미터 개수를 다르게 할 수 있음.
type Add = {
  (a: number, b: number): number
  (a: number, b: number, c: number): number
}

🔻

type Add = {
  (a: number, b: number): number;
  (a: number, b: number, c: number): number;
};

const add: Add = (a, b, c?: number) => {
  if (c) return a + b + c;
  return a + b;
};

add(1, 2);  // 3
add(1, 2, 3);  // 6

Polymorphism

✅ 다형성(polymorphism) 이란?

  • 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미
  • 예제
    배열을 받아 각 요소를 하나씩 출력하는 함수
type PrintArr = {
  (arr: number[]): void
}

const printArray: PrintArr = (arr) => {
  arr.forEach(i => console.log(i);
}
type PrintArr = {
  (arr: number[]): void;
  (arr: boolean[]): void;
  (arr: string[]): void;
};

const printArray: PrintArr = (arr) => {
  arr.forEach((i) => console.log(i));
};

printArray([1, 2, 3]);
printArray([true, true, false]);
printArray(['a','b', 'c']);

만약 number, boolean, string 에 대한 각각의 call signature을 선언해주면
아래와 같은 경우에는 오류가 발생한다.

printArray(['1', 'a', true]);  // ❗️ error

❗️ 참고

(arr: (number | string | boolean)[]): void

위와 같이 OR 기호 이용시 가능하지만, 위와같은 방법은 모든 경우를 다 따져야 하므로 권장하지 않음

🔻

대신, generic을 사용하자.

generic

  • type의 placeholder 역할을 함.
// 🔻 Generic 사용
type PrintArr = {
  <TypePlaceholder>(arr: TypePlaceholder[]): void
};

const printArray: PrintArr = (arr) => {
  arr.forEach((i) => console.log(i));
};

printArray([1, 2, 3]);
printArray([true, true, false]);
printArray(['a', 'b', 'c']);
printArray([1, 'a', true]); // error 발생하지 X.

위와 같이 <generic>(arr: generic[]) 형태로 함수 call signature이 나온다.

  • 만약 리턴 타입을 바꾸려면,
type PrintArr = {
  <TypePlaceholder>(arr: TypePlaceholder[]): TypePlaceholder
};

const printArray: PrintArr = (arr) => {
    return arr[0];
};
profile
기억은 한계가 있지만, 기록은 한계가 없다.

0개의 댓글