본 포스트는 인프런의 타입스크립트 입문-기초부터 실전까지 강의(링크)를 듣고 정리한 내용입니다.


재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징

한 가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트 생성에 사용


// JavaScript function logText(text) { console.log(text); return text; } logText('Hello'); logText(10); logText(true);
  • JS 문법의 경우 위와 같은 함수에서는 어떤 것이든 인자로 사용 가능

// TypeScript function logText<T>(text: T): T { console.log(text); return text; } logText<string>('Hello');
  • TS의 generic을 활용하면 함수를 호출할 때 type을 정의하겠다는 약속
  • 함수를 추상화해서 더 다양한 type에서 사용 가능

image
  • 함수 호출에서 type을 정의하면 해당하는 type의 전달과 출력이 type으로 지정

function logText(text: string) { console.log(text); return text; } function logNumber(num: number) { console.log(num); return num; } logText('a') logNumber(10)
  • 기존 TS 문법은 type에 따라 함수를 중복 정의 해야한다.
  • 유지보수 차원에서 좋지 않음

function logText(text: string | number) { console.log(text); return text; }

문제점1. 지정된 여러 type이 공통으로 가지는 method에서만 preview 지원

image

문제점2. 한 가지 타입에서만 존재하는 메서드 사용 불가

image
  • 해당 함수의 결과값은 union type이므로 한 가지 type에서만 지원하는 메서드 사용 불가

function logText<T>(text: T): T { console.log(text); return text; } const str = logText<string>('a') str.split('') const num = logText<number>(10) num.toLocaleString()
  • generic을 통한 type 정의를 통해 return된 값을 변수로 지정
  • 이 변수는 각 type에서 지원하는 method 사용 가능
image

interface Dropdown<T> { value: T; selected: boolean; } const obj1: Dropdown<string> = { value: 'abc', selected: false }; const obj2: Dropdown<number> = { value: 10, selected: false };

function logTextLength<T>(text: T): T { console.log(text.length); return text; } logTextLength('hi');
  • 함수 내부에서 인자의 메서드 사용은 인자의 type마다 다르다.
  • generic에서 type은 호출 때 정의되므로, 함수 작성 시에는 오류 발생
image

힌트를 주자!

  • text는 length를 셀 수 있는 애라는 것을 알린다!
  • text는 배열이라고 가정
function logTextLength<T>(text: T[]): T[] { console.log(text.length); text.forEach(function (text) { console.log(text); }) return text; } logTextLength<string>(['hi', 'abc']);
  • 실제 인자도 Array 형태로 전달해야 한다.

interface LengthType { length: number; } function logTextLength<T extends LengthType>(text: T): T { text.length; return text; } logTextLength('abcdef'); logTextLength(['a', 'b', 'c', 'd']) logTextLength({ length: 10 }) logTextLength(10);
  • 정의될 Type은 length 속성/메서드를 가진 LengthType의 상속을 받는 type이 된다.
  • T type은 LengthType에 추가로 정의
image

interface ShoppingItem { name: string; price: number; stock: number; } function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T): T { return itemOption; } getShoppingItemOption('name');

interface의 key들 중 하나를 인자로 사용


function fetchItems(): Promise<string[]> { let items = ['a', 'b', 'c']; return new Promise(function (resolve) { resolve(items); }) } fetchItems();

findContactByPhone(phoneNumber: number, phoneType: string): Contact[] { return this.contacts.filter( contact => contact.phones[phoneType].num === phoneNumber ); }

이런 함수의 경우 인자로 phoneType을 받는다.

findContactByPhone('Homee');

그런데 이런 경우 오타를 방지할 수 없기 때문에 아래와 같이 enum을 사용


enum PhoneType { Home = 'home', Office = 'office', Studio = 'studio', }
findContactByPhone(PhoneType.Home);

오타에 대한 에러를 바로 확인 가능