From 70c4ec0b61543435b23494d9385406d11e61b302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=8A=B9=ED=9B=88?= Date: Fri, 29 Jul 2022 01:49:15 +0900 Subject: [PATCH 1/2] #47 Post. Advanced TypeScript --- .../220729.md" | 345 ++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 "\353\260\225\354\212\271\355\233\210/220729.md" diff --git "a/\353\260\225\354\212\271\355\233\210/220729.md" "b/\353\260\225\354\212\271\355\233\210/220729.md" new file mode 100644 index 0000000..dd64def --- /dev/null +++ "b/\353\260\225\354\212\271\355\233\210/220729.md" @@ -0,0 +1,345 @@ +# TypeScript 고급 + +## 제네릭(Generics) + +### 제네릭이란? + +> 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징 + +**한 가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트 생성에 사용** + +
+ +```js +// JavaScript +function logText(text) { + console.log(text); + return text; +} + +logText('Hello'); +logText(10); +logText(true); +``` + +- JS 문법의 경우 위와 같은 함수에서는 어떤 것이든 인자로 사용 가능 + +
+ +```ts +// TypeScript +function logText(text: T): T { + console.log(text); + return text; +} + +logText('Hello'); +``` + +- TS의 generic을 활용하면 **함수를 호출할 때 type을 정의하겠다**는 약속 +- 함수를 추상화해서 더 다양한 type에서 사용 가능 + +
+ +![image](https://user-images.githubusercontent.com/86189596/173964717-a4c8de60-89e0-4b87-86ec-4c0109d70768.png) + +- 함수 호출에서 type을 정의하면 해당하는 type의 전달과 출력이 type으로 지정 + +
+ +### 기존 TS 함수의 중복 선언 + +```js +function logText(text: string) { + console.log(text); + return text; +} + +function logNumber(num: number) { + console.log(num); + return num; +} + +logText('a') +logNumber(10) +``` + +- 기존 TS 문법은 type에 따라 함수를 중복 정의 해야한다. +- 유지보수 차원에서 좋지 않음 + +
+ +### 유니온 타입을 이용한 선언 방식 문제점 + +```ts +function logText(text: string | number) { + console.log(text); + return text; +} +``` + +> 문제점1. 지정된 여러 type이 공통으로 가지는 method에서만 preview 지원 + +![image](https://user-images.githubusercontent.com/86189596/173974315-b5d3e702-f8a2-4973-9cb6-a3deecd59a2f.png) + +
+ +> 문제점2. 한 가지 타입에서만 존재하는 메서드 사용 불가 + +![image](https://user-images.githubusercontent.com/86189596/173974478-986beeef-1030-488e-9c90-277e99a356d1.png) + +- 해당 함수의 결과값은 union type이므로 한 가지 type에서만 지원하는 메서드 사용 불가 + +
+ +### 제네릭의 장점과 타입 추론에서의 이점 + +```ts +function logText(text: T): T { + console.log(text); + return text; +} + +const str = logText('a') +str.split('') + +const num = logText(10) +num.toLocaleString() +``` + +- generic을 통한 type 정의를 통해 return된 값을 변수로 지정 +- 이 변수는 각 type에서 지원하는 method 사용 가능 + +![image](https://user-images.githubusercontent.com/86189596/174127271-80278ded-b588-43da-9279-1f610984da11.png) + +
+ +### 인터페이스에 제네릭 선언 + +```ts +interface Dropdown { + value: T; + selected: boolean; +} + +const obj1: Dropdown = { value: 'abc', selected: false }; +const obj2: Dropdown = { value: 10, selected: false }; +``` + +
+ +### 제네릭의 타입 제한 + +```ts +function logTextLength(text: T): T { + console.log(text.length); + return text; +} + +logTextLength('hi'); +``` + +- 함수 내부에서 인자의 메서드 사용은 인자의 type마다 다르다. +- generic에서 type은 호출 때 정의되므로, 함수 작성 시에는 오류 발생 + +![image](https://user-images.githubusercontent.com/86189596/174138959-ca4af74a-ed1e-423a-a748-374fb2e61ac4.png) + +
+ +> 힌트를 주자! + +- text는 length를 셀 수 있는 애라는 것을 알린다! +- text는 배열이라고 가정 + +```ts +function logTextLength(text: T[]): T[] { + console.log(text.length); + text.forEach(function (text) { + console.log(text); + }) + return text; +} + +logTextLength(['hi', 'abc']); +``` + +- 실제 인자도 Array 형태로 전달해야 한다. + +
+ +### 제네릭의 타입 제한2 : 정의된 타입 이용 + +```ts +interface LengthType { + length: number; +} + +function logTextLength(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](https://user-images.githubusercontent.com/86189596/174140574-08be9372-f30c-4fd0-9803-624eca70aeb1.png) + +
+ +### 제네릭의 타입 제한3 : keyof 이용 + +```ts +interface ShoppingItem { + name: string; + price: number; + stock: number; +} + +function getShoppingItemOption(itemOption: T): T { + return itemOption; +} +getShoppingItemOption('name'); +``` + +interface의 key들 중 하나를 인자로 사용 + +
+ +## Promise를 이용한 API 함수 타입 정의 + +```ts +function fetchItems(): Promise { + let items = ['a', 'b', 'c']; + return new Promise(function (resolve) { + resolve(items); + }) +} +fetchItems(); +``` + +
+ +## enum을 이용한 타입 정의 + +```ts +findContactByPhone(phoneNumber: number, phoneType: string): Contact[] { + return this.contacts.filter( + contact => contact.phones[phoneType].num === phoneNumber + ); +} +``` + +
+ + +이런 함수의 경우 인자로 phoneType을 받는다. + +```ts +findContactByPhone('Homee'); +``` + +그런데 이런 경우 오타를 방지할 수 없기 때문에 아래와 같이 enum을 사용 + +
+ +```ts +enum PhoneType { + Home = 'home', + Office = 'office', + Studio = 'studio', +} +``` + +```ts +findContactByPhone(PhoneType.Home); +``` + +오타에 대한 에러를 바로 확인 가능 + +
+ +## 타입 추론(Type Inference) + +### 타입 추론이란? + +```ts +// parameter의 type으로 return 값의 type이 결정 +function getB(b) { + return b; +} +``` + +```ts +// parameter의 type으로 return 값의 type이 결정 +function getB(b) { + const c = 'hi' + return b + c; +} +``` + +- number + string = string으로 type 추론 +- return 값이 내부적으로 string으로 추론 + +
+ +### 인터페이스와 제네릭에서의 타입 추론 + +> 인터페이스와 제네릭 + +```ts +interface Dropdown { + value: T; + title: string; +} + +const shoppingItem: Dropdown = { + value: 'abc', + title: 'hello', +} +``` + +
+ +> 인터페이스의 상속 + +```ts +interface Dropdown { + value: T; + title: string; +} + +// 관행적으로 T를 쓰지만 구분을 위해 K 사용 +interface DetailedDropdown extends Dropdown { + description: string + tag: K; +} + +const detailedItem: DetailedDropdown = { + value: 'abc', + title: 'hello', + description: '안녕하세요~~', + tag: 'a' +} +``` + +인터페이스 A를 상속받은 인터페이스 B는 generic의 Type도 상속 가능 + +
+ +### Best Common Type + +> 배열 내에 type이 여러 종류가 있는 경우 + +```ts +const arr: (number | string | boolean)[] = [1, 2, 3, 'a', 'b', 'c', true]; +``` + +유니온 타입을 이용해 배열에 들어간 개체들의 타입을 추론해 union type으로 정의 + +![image](https://user-images.githubusercontent.com/86189596/174268126-33d74c33-0a86-45fc-919e-3d08201a55fc.png) \ No newline at end of file From 03bec1835c63f98309f049bd106af8f982d84167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=8A=B9=ED=9B=88?= Date: Fri, 29 Jul 2022 21:12:50 +0900 Subject: [PATCH 2/2] #47 Post. video link --- "\353\260\225\354\212\271\355\233\210/220729.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/\353\260\225\354\212\271\355\233\210/220729.md" "b/\353\260\225\354\212\271\355\233\210/220729.md" index dd64def..fb9d294 100644 --- "a/\353\260\225\354\212\271\355\233\210/220729.md" +++ "b/\353\260\225\354\212\271\355\233\210/220729.md" @@ -1,5 +1,7 @@ # TypeScript 고급 + + ## 제네릭(Generics) ### 제네릭이란?