diff --git "a/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.1_\355\203\200\354\236\205\354\212\244\355\201\254\353\246\275\355\212\270\353\247\214\354\235\230_\353\217\205\354\236\220\354\240\201_\355\203\200\354\236\205_\354\213\234\354\212\244\355\205\234/seongho.md" "b/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.1_\355\203\200\354\236\205\354\212\244\355\201\254\353\246\275\355\212\270\353\247\214\354\235\230_\353\217\205\354\236\220\354\240\201_\355\203\200\354\236\205_\354\213\234\354\212\244\355\205\234/seongho.md"
index 3beced8..10d4630 100644
--- "a/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.1_\355\203\200\354\236\205\354\212\244\355\201\254\353\246\275\355\212\270\353\247\214\354\235\230_\353\217\205\354\236\220\354\240\201_\355\203\200\354\236\205_\354\213\234\354\212\244\355\205\234/seongho.md"
+++ "b/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.1_\355\203\200\354\236\205\354\212\244\355\201\254\353\246\275\355\212\270\353\247\214\354\235\230_\353\217\205\354\236\220\354\240\201_\355\203\200\354\236\205_\354\213\234\354\212\244\355\205\234/seongho.md"
@@ -1 +1,259 @@
-
+## 타입스크립트만의 독자적 타입 시스템
+ts에서 내포하고 있는 개념은 모두 js에서 기인한 것 임
+ts의 `any`타입을 살펴보자. js에서 변수 타입을 아무리 추적해봐도, any라는 문자열을 반환하는 경우는 찾을 수 없음. `any`는 ts만의 독자적인 타입 시스템이기 때문.
+
+타입스크립트의 타입 계층구조는 아래와 같음.
+
+
+
+
+### 1. `any`타입
+any타입은 앞서 말한대로 js에 존재하는 모든 값을 오류없이 받을 수 있음.
+따라서 any로 지정한 타입에 어떠한 값을 할당하더라도 오류가 발생하지 않음.
+```ts
+let a: any;
+
+a = 1;
+a = 'Hello';
+a = () => {};
+a = {};
+```
+이러한 any는 사실 ts의 정적 타이핑의 방향과는 맞지 않기때문에 최대한 사용을 지양해야 함.
+하지만 어쩔수 없는 환경이라는 것이 있는 법. 대표적으로 3가지 경우가 있음.
+
+- **개발 단계에서 임시로 값을 지정해야 하는 경우**
+ 아직 API의 세부 스펙이 나오지 않았거나, 확정되지 않았을 경우 `any`타입을 임시로 할당해 준 뒤, 이후 세부 스펙이 나왔을 때 다른 타입으로 대체하는 경우가 많음.
+
+
+
+- **어떤 값을 받아올지 또는 넘겨줄지 정할 수 없을 경우**
+ _API 요청 및 응답 처리_, _콜백함수 전달_, _타입이 잘 정제되지 않아 파악이 힘든 외부 라이브러리_ 를 사용하는 경우 `any`타입을 사용할 수 있음.
+
+ ```ts
+ type ModalParams = {
+ show: boolean;
+ content: string;
+ action?: any;
+ }
+ ```
+ `ModalParams`를 보면 `action`타입이 `any`로 선언되어져 있는데, 모달의 특성상 모든 액션에 인자의 갯수나, `return`값을 모두 명시해줄 수 없을 때 `any`를 사용할 수 있음.
+
+
+
+- **값을 예측할 수 없을 경우 암묵적으로 사용**
+ fetch와 API는 요청 이후 응답을 특정 포맷으로 파싱하는데, 이때 반환 타입이 any로 매핑되어져 있음.
+ ```ts
+ async function fetchAPI() {
+ const res = await fetch('https://api.com');
+ const data = await res.json(); // res.json()의 타입은 Priomise
+
+ return data;
+ }
+ ```
+
+
+
+> [!WARNING]
+> `any`타입은 편의성과 확장성을 제공하지만 컴파일러가 에러를 잡지 못하기 때문에 실제 런타임에서 심각한 오류가 발생할 수 있으니, 최대한 사용을 지양하자
+
+
+
+### 2. `unknown` 타입
+`unknown`타입은 `any`타입과 유사하게 모든 타입의 값이 할당 될 수 있음.
+**_그러나 unknown타입으로 선언된 값은 any를 제외하고, 다른 타입으로 선언된 변수에 할당할 수 없음_**
+
+> [!NOTE]
+> **`any` vs `unknown`**
+> | any | unknown |
+> |--|--|
+> | - 어떤 타입이든 any에 할당 가능
- `any`타입으로 선언된 변수는 어디든 할당 가능 | - 어떤 타입이든 unknown에 할당 가능
- `unknown`타입으로 선언된 변수는 any타입 외에 다른 타입으로 선언된 변수에 할당 불가능 |
+>
+>
+
+
+
+`unknown`의 특징은 함수를 unknown타입에 할당할때는 컴파일러가 경고를 주지는 않지만, 실행하려고 하면 에러가 발생함.
+
+-> 원시값의 사용은 에러를 뱉지 않지만 함수, 객체, 배열로 접근하려고 하면 에러를 뱉음
+
+앞서, `any`를 사용하는 경우중에 어떤 값이 할당될지 파악하기 어려운 상황에서 `any`타입을 임시로 지정하여 개발하다가, 추후 any타입을 수정해야 하는 것을 **깜빡하고 누락하면** 큰일이 발생함.
+타입이 식별된 후에 사용이 가능한 unknown타입은 이런 불상사를 보완하기 위해서 등장한 타입임.
+따라서 `any`타입 대신에 `unknown`으로 대체해서 사용하는 방법이 권장 됨.
+
+
+
+### 3. `void` 타입
+함수가 아무것도 반환하지 않는 경우에 사용하는 타입. (함수가 아닌 곳에서도 할당이 가능하지만, 무의미함)
+```ts
+function runCallback(callback: CallbackType): void {
+ callback();
+}
+```
+js에서 아무것도 리턴하지않으면 암묵적으로 `undefined`를 리턴하지만 이건 `void`와는 다름.
+명시적인 의미를 부여하는 관점에서 `undefined`와 `null`, `void`를 의미에 맞게 사용하자.
+
+
+
+### 4. `never` 타입
+never타입도 일반적으로 함수와 관련해서 많이 사용되는 타입으로서, **값을 반환할 수 없는 타입**을 말함.
+여기서 중요한 건 반환을 **`안`하는 거**랑 **`못`하는 거**를 명확히 구분 해야 함.
+**못하는 경우**는 대표적으로 두가지 경우가 있음.
+- 에러를 던지는 경우
+ ```ts
+ function generateError(): never {
+ throw new Error();
+
+ // ...
+ }
+ ```
+- 무한히 함수가 실행되는 경우(infinity loop)
+ ```ts
+ function infiniteLoop(): never {
+ while (true) {
+ // do something..
+ }
+ }
+ ```
+
+
+`never`타입은 모든 타입의 하위 타입으로서 never로 선언된 변수에는 어떠한 타입도 할당될 수 없음.
+ts에서는 조건부 타입을 결정할 때 엄격한 타입검사 목적으로 never타입을 명시적으로 사용하기도 함.
+
+
+
+### 5. `Array`타입
+js에서의 배열은 동적 언어의 특징에 따라 어떤 값이든 배열의 원소로 허용함.
+
+```tsx
+function fn() {};
+
+const arr = [1, "string", fn];
+```
+
+하지만 이런 개념은 ts의 정적타이핑에 부합하지 않음.
+
+따라서 ts에서는 배열의 크기까지 제한하지는 않지만, 정적타입의 특성을 살려
+명시적인 타입을 선언하여 해당 타입의 원소를 관리하는 것을 강제함.
+
+```ts
+const arr: number[] = [1, 2, 3];
+```
+
+→ 숫자에 해당하는 원소만 허용함.
+Array는 `제네릭`이라는 특수한 문법으로도 선언이 가능함.
+
+```ts
+const arr: Array = [1, 2, 3];
+```
+
+두 선언방식의 차이점은 없음.
+만약, 여러 타입을 모두 관리해야 하는 배열을 선언하려면 `유니온 타입`을 사용할 수 있음
+
+```ts
+const arr: Array = [1, "string"];
+const arr2: (number | string)[] = [1, "string"];
+```
+
+
+
+그러나 여기에 **배열의 길이**까지 제한하고 싶다면 `튜플` 이라고 하는 타입 시스템을 사용할 수 있음.
+튜플은 배열의 길이까지 제한하여 **원소타입**과, **갯수**를 보장함.
+```ts
+let tuple: [number] = [1];
+
+tuple = [1, 2]; // Error!
+tuple = ['string']; // Error!
+
+let tuple2: [number, string] = [1, 'string']; // ✅
+```
+튜플은 컨벤션을 잘 지키고, 배열 원소의 명확한 의미와 쓰임을 보장하면 더욱 안전하게 사용할 수 있음.
+
+***예를 들어 리액트의 `useState` 훅을 살펴보자.***
+`useState훅`은 튜플 타입을 반환함.
+`첫번째 원소`는 훅으로부터 생성 및 관리되는 상태 값을 의미하고, `두번째 원소`는 해당 상태를 조작할 수 있는 setter를 의미함.
+또한 `구조 분해 할당`을 사용해서 사용자가 자유롭게 이름을 정의할 수 있음.
+`useState`는 **반환값이 명확**하고, **잘 설계된 API**이므로 `튜플` 타입을 통해서 유연성을 얻을 수 있음.
+
+
+
+ 튜플과 배열의 성질을 혼합해서 사용할 수도 있는데 일부는 튜플로 엄격하게 제한하고, 나머지는 배열처럼 동작하게 할 수도 있음.
+ ```ts
+ // 첫번째 원소는 number타입, 나머지는 string만 올 수 있음
+ type TupleAndArray = [number, string, ...string[]];
+
+ function some(arr: TupleAndArray) {
+ // do something..
+ }
+ ```
+
+
+> [!TIP]
+> **`옵셔널(optional)`**
+> 선택적으로 속성을 명시하고 싶다면 물음표 기호(`?`)와 함께 해당 속성을 선언할 수 있음.
+> 이는, 옵셔널하기 때문에 필수적으로 자리잡고 있지 않을 수 있음을 의미함.
+> ```tsx
+> const arr: [number, string, boolean?] = [1, "Hello"];
+> ```
+
+
+
+### 6. `enum` 타입
+enum타입은 `열거형`이라고도 부르는데, ts에서 지원하는 특수한 타입임.
+enum을 사용해서 열거형을 정의할 수 있는데 열거형은 각각의 `멤버` 라는 것을 가짐.
+약간 객체와 비슷한데, **_ts는 각 멤버의 값이 없다면 스스로 추론함._**
+기본적인 추론 방식은 숫자 0부터 1씩 늘려가면서 값을 할당함.
+
+```ts
+enum enumValue {
+ ts,
+ js,
+ react,
+ next,
+}
+
+console.log(enumValue.ts); // 0
+// 역방향으로도 접근이 가능함
+console.log(enumValue[0]); // 'ts'
+```
+
+
+당연하게도 각 멤버에 명시적으로 값을 할당하는 것도 가능함.
+그리고 일부 멤버에 값을 할당하지 않아도, 이전 멤버 값의 숫자를 기준으로 1씩 늘리면서 자동으로 할당함.
+**_(그래서 값을 일부만 명시적으로 할당하는 경우 명시적으로 할당하는 마지막 멤버는 숫자를 할당해야 함)_**
+
+
+근데 enum은 숫자로만 이루어져 있거나, ts가 자동으로 추론한 열거형은 안전하지 않은 결과를 낳을 수 있음.
+역방향으로 접근 할 시 범위를 넘어서 접근하더라도 에러가 발생하지 않음.
+```ts
+enum EnumValue {
+ ONE,
+ TWO,
+}
+
+EnumValue[100]; // ✅ undefined
+```
+
+그래서 이러한 동작을 막기 위해서 `const enum`으로 enum을 선언하는 방법이 있음.
+**`const enum`은 역방향 접근을 허용하지 않음.**
+
+```ts
+const enum EnumValue {
+ ONE,
+ TWO,
+}
+
+console.log(EnumValue[1]); // Error : A const enum member can only be accessed using a string literal.
+```
+
+
+
+> [!CAUTION]
+> **_"const enum으로 선언하더라도, 숫자상수로 관리되는 열거형은 선언값 이외의 값을 할당하거나, 접근할때 이를 방지하지 못한다.
+반면 문자열 상수 방식으로 열거형을 사용하는 것은 접근을 방지한다."_**
+-> 이렇게 책에 적혀져 있는데, 테스트 결과 숫자 상수 열거형도 선언값 이외의 값에 접근이 불가함❗️❗️❗️❗️
+
+
+enum의 가장 큰 문제는 enum이 타입 공간과, 값 공간에 모두 사용되는 타입이고 컴파일을 하면 `즉시실행함수(IIFE)`로 변환이 되는 것을 보았음.
+
+이 때문에 일부 번들러에서 사용되지 않는 `enum`이라고해도 `즉시실행함수`이기 때문에 `트리 쉐이킹` 과정중 사라지지 않는 문제가 발생함.
+이는 곧 **번들 사이즈의 증가**로 이어짐
diff --git "a/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.2_\355\203\200\354\236\205_\354\241\260\355\225\251/seongho.md" "b/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.2_\355\203\200\354\236\205_\354\241\260\355\225\251/seongho.md"
index 3beced8..8482a71 100644
--- "a/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.2_\355\203\200\354\236\205_\354\241\260\355\225\251/seongho.md"
+++ "b/CH03_\352\263\240\352\270\211_\355\203\200\354\236\205/3.2_\355\203\200\354\236\205_\354\241\260\355\225\251/seongho.md"
@@ -1 +1,312 @@
-
+## 타입 조합
+앞에서 다룬 개념을 응용하거나, 내용을 덧붙여서 좀 더 심화한 타입 검사를 수행해보자
+
+
+
+### 1. 교차 타입(Intersection)
+`교차 타입`을 사용하면 여러가지 타입을 결합하여 하나의 단일 타입으로 만들 수 있음.
+교차 타입은 `&`을 사용해서 표기함.
+```ts
+interface Person {
+ name: string;
+ age: number;
+};
+
+type PersonWithLocation = Person & { location: string };
+```
+
+
+
+### 2. 유니온 타입(Union)
+교차 타입의 A & B가 타입 A와 타입 B를 모두 만족하는 경우라면, `유니온 타입`은 타입 A 또는 타입 B중 하나가 될 수 있는 타입을 말함.
+```ts
+interface Person {
+ name: string;
+ age: number;
+};
+
+interface Duck {
+ name: string;
+ leg: boolean;
+}
+
+type C = Person | Duck;
+
+
+function foo(bar: C) {
+ bar.name;
+ bar.leg; // Error : Property 'leg' does not exist on type 'Person'.
+}
+```
+해당 예시를 보면 bar는 `Person`과 `Duck`의 유니온 타입인 `C`를 bar의 타입으로 선언해주었음.
+근데, bar는 `Person`일지, `Duck`일지 모르는 상황이기 때문에 두 타입이 공통으로 갖는 name에는 접근이 가능하지만 `Duck`만 갖고있는 `leg` 프로퍼티에는 접근할 수 없음.
+
+
+
+### 3. 인덱스 시그니처(Index Signatures)
+`인덱스 시그니처`는 **_특정 타입의 속성 이름은 알 수 없지만, 속성과 속성값의 타입을 알고있을 때_** 사용하는 문법.
+인터페이스 내부에 `[key: T]: K` 꼴로 타입을 명시해줌.
+이는 key는 `T`타입이여야 하고, value는 `K`타입이어야 함을 의미함.
+```ts
+interface IndexSignature {
+ [key: '']: number;
+}
+
+let obj: IndexSignature;
+
+obj = { name: 1 };
+obj = { name: true }; // Error : Type 'boolean' is not assignable to type 'number'.
+```
+당연하게 `유니온 타입`도 가능함.
+```ts
+interface IndexSignature {
+ [key: string]: number | string;
+}
+
+let obj: IndexSignature;
+
+obj = { name: 'seongho', age: 27 }; // ✅
+
+interface IndexSignature2 {
+ [key: string | number]: number;
+}
+
+let obj2: IndexSignature2;
+
+obj2 = { 1 : 1 }; // ✅
+
+```
+
+> [!CAUTION]
+> 인덱스 시그니처의 key의 타입은 `string`, `number`, `symbol`, `템플릿 리터럴`타입만 가능함.
+> ```ts
+> interface IndexSignature {
+> [key: boolean]: number | string; // Error : An index signature parameter type must be 'string', 'number', 'symbol', or a template literal type.
+> }
+>
+> let obj: IndexSignature;
+>
+> obj = { name: 'seongho', age: 27 };
+> ```
+
+
+
+### 4. 인덱스 엑세스 타입(Index Access Types)
+`인덱스 엑세스 타입`은 말 그대로 인덱스로 접근해서 타입을 가져오는 것임.
+인덱스에 사용되는 타입도 그 자체로 타입이라서 `유니온`이나 `keyof`, `타입 별칭(type키워드로 선언한 타입)`등 모두 가능함.
+```ts
+interface IndexAccess {
+ a: number;
+ b: string;
+ c: boolean;
+}
+
+type A = IndexAccess['a']; // number;
+type B = IndexAccess['a' | 'b']; // number | string;
+type C = IndexAccess[keyof IndexAccess]; // number | string | boolean;
+
+type typeAlias = 'b' | 'c'; // 타입 별칭
+
+type D = IndexAccess[typeAlias]; // string | boolean;
+```
+
+인덱스 엑세스 타입은 **배열의 요소 타입**을 조회하기 위해 사용되기도 함.
+```ts
+const arr = [1, 'name', true];
+type StringList = string[];
+
+type ItemType = typeof arr[number]; // number | string | boolean
+type ItemType2 = StringList[number]; // number
+
+// ======================
+
+const me = [
+ { name: 'seongho', age: 27 },
+];
+
+type InformationOf> = T[number];
+
+const seongho100: InformationOf = {
+ name: '오성오',
+ age: 100,
+}
+```
+
+
+
+### 5. 맵드 타입(Mapped Types)
+js에서의 map이라고 하면, 배열 A를 기반으로 새로운 배열 B를 만들어 내는 배열 메서드임.
+이처럼 ts에서의 `맵드 타입`도 ***다른 타입을 기반으로 한 타입을 선언할 때 사용하는 문법*** 임. 이때 `인덱스 시그니처` 문법을 사용하면 더욱 효과적으로 사용할 수 있음.
+```ts
+type Example = {
+ a: string;
+ b: number;
+ c: boolean;
+}
+
+type Subset = {
+ [K in keyof T]?: T[K];
+}
+
+const list = [
+ { name: 'seongho', age: 27 },
+]
+
+const withLoc = { name: 'seongho', age: 27, location: 'gp' };
+
+const a: Subset = { a: 'string' };
+const b: Subset = { b: 2 };
+const c: Subset = withLoc;
+```
+
+
+특이한 점은 `맵드 타입`에서 타입을 매핑할때는 `readonly`나 `?`를 수식어로 적용할 수 있다는 점인데, 추가하는 것은 물론이고 빼는것도 가능함.
+```ts
+type Example = {
+ a: string;
+ b: number;
+ c: boolean;
+}
+
+type Subset = {
+ [K in keyof T]?: T[K];
+}
+
+// Subset에서 추가한 optional을 제거
+type Require = {
+ [K in keyof T]-?: T[K];
+}
+
+const a: Subset = { a: 'string' };
+let b: Require>;
+
+b = { b: 2 }; // Error!
+b = { a: 'a', b: 1, c: true }; // ✅
+```
+
+
+
+덧붙여서 `as`키워드를 통해서 key의 이름을 재지정 할 수도 있음.
+```ts
+type Example = {
+ a: string;
+ b: number;
+ c: boolean;
+}
+
+type Keys = keyof Example;
+
+type WithOptionalSeonghoInKey = {
+ [K in Keys as `${K}_Seongho`]?: {
+ name: string;
+ age: number;
+ }
+}
+
+const obj: WithOptionalSeonghoInKey = {
+ a_Seongho: {
+ name: '에이성호',
+ age: 27,
+ },
+ b_Seongho: {
+ name: '비성호',
+ age: 25,
+ }
+}
+```
+
+
+
+### 6. 템플릿 리터럴 타입(Template Literal Types)
+`템플릿 리터럴 타입`은 js의 템플릿 리터럴 문자열(``)을 사용해서 문자열 리터럴 타입을 선언할 수 있는 문법임.
+위에서 본 예시에 템플릿 리터럴 타입도 같이 포함되어져 있음. 조금 더 간단한 예시로 다시 봐보자
+
+
+이처럼 `템플릿 리터럴`을 사용해서 변수자리에 `문자열 리터럴 유니온 타입`을 넣으면, 각 유니온 타입의 멤버들이 차례대로 해당 변수로 들어가서 재가공 됨.
+
+
+
+### 7. 제네릭(Generic)
+제네릭은 보통 C나 Java와 같은 정적 언어에서 타입간의 재사용성을 높이기 위해서 사용하는 문법임. ts도 `정적 타입`을 가지는 언어이기때문에 `제네릭` 문법을 지원하고 있음.
+
+ts의 제네릭을 조금 더 풀어서 보면 `함수`, `타입`, `클래스` 등에서 내부적으로 사용할 타입을 미리 정해두지 않고, 타입 변수를 사용해서 해당 위치를 비워둔 뒤 실제로 해당 값을 사용할 때 외부에서 `타입 변수` 자리를 사용해 타입을 지정해서 사용하는 방식임.
+`타입 변수`는 주로 ``와 같이 꺾쇠 괄호 내부에 정의하고, 매개변수를 넣는것과 유사하게 원하는 타입을 넣어주면 됨.
+
+```ts
+type ArrayType = T[];
+
+const stringArray: ArrayType = ['hello', 'world'];
+```
+
+> [!TIP]
+> **제네릭의 컨벤션**
+> 보통 타입 변수명으로 `T(Type)`, `E(Element)`, `K(Key)`, `V(Value)`등 한글자로 된 이름을 많이 사용함.
+
+> [!CAUTION]
+> **`any`와 `제네릭`은 달라요**
+> 둘의 명확한 차이점은 배열을 예로 들어보면 편한데, `any`타입의 배열에는 배열 요소들이 전부 같지 않을 수 있음
+> 하지만 제네릭은 `any`처럼 아무 타입이나 무분멸하게 받는게 아니라, 배열의 생성 시점에 원하는 타입으로 특정하는 것임.
+> ```ts
+> type AnyArray = any[];
+> type ArrayType = T[];
+>
+> const list1: AnyArray = [1, 'hello', true, () => {}]; // 아무거나 가능
+> const list2: ArrayType = [1, 2, 3, 4];
+> const list3: ArrayType = [1, 'hello', true, () => {}]; // > Error!
+> ```
+
+
+
+제네릭 함수를 호출 할 때 ***반드시*** 꺽쇠괄호 안에 타입을 명시해줘야 되는 것은 아님. 타입을 명시하는 부분을 생략하면 컴파일러가 `인자`를 보고 타입을 추론 해줌.
+
+-> 인자에 string타입의 값이 들어와서 컴파일러가 제네릭 함수에 들어온 인자값을 보고 타입을 스스로 추론했음.
+
+만약 특정 요소의 타입을 알 수 없는 경우에는 `타입 기본값`도 할당해 줄 수 있음.
+
+
+
+
+***제네릭을 사용할때 항상 유의헤야 하는 점은 제네릭에는 어떤 타입이든 올 수 있다는 점임.***
+이걸 왜 유의해야 하냐? 이는 곧, **특정 타입에만 존재하는 프로퍼티나 메서드를 참조하려고 하면 안된다는 뜻**임!!
+예를 들자면
+```ts
+function genericFunc(params: T): number {
+ return params.length; // Error : Property 'length' does not exist on type 'T'.
+}
+```
+이런거임.
+
+`length`는 배열에만 존재하는 프로퍼티고, T에는 어떤 타입이 올지 모르기 때문. 이 문제는 기본 타입을 할당해줘도 해결이 안됨.
+```ts
+function genericFunc(params: T): number {
+ return params.length; // Error : Property 'length' does not exist on type 'T'.
+}
+```
+
+
+만약, 어떤 타입이 올지 모르지만 `length` 프로퍼티는 반드시 갖는 프로퍼티만 오게 하고 싶다면, 제약을 걸어서 만족시켜줄 수 있음.
+```ts
+interface HasLengthProperty {
+ length: number;
+}
+
+function genericFunc(params: T): number {
+ return params.length;
+}
+
+function foo(a: number, b: string, ...params: unknown[]) {
+ genericFunc(arguments); // arguments는 유사 배열이므로 length 프로퍼티를 가지기 때문에 가능.
+ genericFunc(params); // 배열도 가능. 배열도 js에서는 객체니까
+ genericFunc({
+ length: 1,
+ name: 'seongho'
+ }); // length프로퍼티를 갖고 있으니까 이것도 가능
+}
+```
+
+> [!CAUTION]
+> **tsx파일에서 화살표 함수에 제네릭을 사용하면 에러가 발생함**
+> 제네릭의 꺾쇠 괄호와 태그의 꺾쇠괄호를 구분할 수 없기 때문임.
+> 아래 이미지를 참고하자.
+>
+>
\ No newline at end of file
diff --git "a/assets/CH03/any\354\231\200unknown.jpeg" "b/assets/CH03/any\354\231\200unknown.jpeg"
new file mode 100644
index 0000000..63266cb
Binary files /dev/null and "b/assets/CH03/any\354\231\200unknown.jpeg" differ
diff --git a/assets/CH03/arrow_function_generic.png b/assets/CH03/arrow_function_generic.png
new file mode 100644
index 0000000..ab4257a
Binary files /dev/null and b/assets/CH03/arrow_function_generic.png differ
diff --git a/assets/CH03/different_book.jpeg b/assets/CH03/different_book.jpeg
new file mode 100644
index 0000000..29c35dc
Binary files /dev/null and b/assets/CH03/different_book.jpeg differ
diff --git a/assets/CH03/enum_a_ju_C.jpeg b/assets/CH03/enum_a_ju_C.jpeg
new file mode 100644
index 0000000..33b69ca
Binary files /dev/null and b/assets/CH03/enum_a_ju_C.jpeg differ
diff --git a/assets/CH03/generic_default.png b/assets/CH03/generic_default.png
new file mode 100644
index 0000000..87dac20
Binary files /dev/null and b/assets/CH03/generic_default.png differ
diff --git a/assets/CH03/generic_type_inference.jpeg b/assets/CH03/generic_type_inference.jpeg
new file mode 100644
index 0000000..ee730d9
Binary files /dev/null and b/assets/CH03/generic_type_inference.jpeg differ
diff --git a/assets/CH03/template_literal.jpeg b/assets/CH03/template_literal.jpeg
new file mode 100644
index 0000000..ae76c31
Binary files /dev/null and b/assets/CH03/template_literal.jpeg differ
diff --git a/assets/CH03/typeHierarchy_of_typescript.jpeg b/assets/CH03/typeHierarchy_of_typescript.jpeg
new file mode 100644
index 0000000..eb9f6fd
Binary files /dev/null and b/assets/CH03/typeHierarchy_of_typescript.jpeg differ
diff --git a/assets/CH03/typle_and_array.jpeg b/assets/CH03/typle_and_array.jpeg
new file mode 100644
index 0000000..8df1532
Binary files /dev/null and b/assets/CH03/typle_and_array.jpeg differ
diff --git a/assets/CH03/unknown_test.jpeg b/assets/CH03/unknown_test.jpeg
new file mode 100644
index 0000000..f7af45b
Binary files /dev/null and b/assets/CH03/unknown_test.jpeg differ