> For the complete documentation index, see [llms.txt](https://haeuns-organization.gitbook.io/megaptera-frontend-course/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://haeuns-organization.gitbook.io/megaptera-frontend-course/week1/2.typescript.md).

# 2. TypeScript

키워드

* REPL
* TypeScript
  * 타입 추론
  * Interface vs Type
  * Union Type vs Intersection Type
  * Optional Parameter

## 타입스크립트, 왜 쓰는가?

* 편리한 자동완성
* 실시간 오류검사

## REPL

* Read-Eval-Print-Loop
* 사용자의 입력을 받아 평가하고 결과를 리턴하는 인터렉티브 프로그래밍 환경
* ts-node를 실행해 타입스크립트 REPL 사용 가능 `npx ts-node`

## 타입 추론

타입스크립트는 자료의 뒤에 타입을 명시

타입을 명시하지 않아도 값을 통해 자동으로 타입을 결정해주기도 함

```ts
const name: string = '홍길동';
const name = '홍길동';
// 위의 코드와 아래코드는 같다.
```

## 타입

### 원시타입

```ts
let name: string;
let age: number;
let isAdult: boolean;

name = "홍길동";
age = 20;
isAdult = true;
```

### 배열

`number[]` 또는 `Array<number>` 의 형태로 사용

```ts
let numbers: number[];
numbers = [1, 2, 3];
```

### 튜플

길이와 타입이 고정된 배열

순서에 맞지 않게 데이터를 넣으면 에러 표시

```ts
let user1: [number, string, string];
user1 = [1, 'setType77@example.com', '1q2w3e4r'];
```

#### 한계점

`push` 메서드를 사용하면 정의와 상관없이 배열의 길이가 늘어남

```ts
let user1: [number, string, string];
user1 = [1, 'setType77@example.com', '1q2w3e4r'];

user1.push('fake'); // 에러없이 컴파일됩니다.
```

#### 해결방안

튜플 선언시에 `readonly` 사용

```ts
type UserInfo = readonly [number , string, string ,string , boolean]; // 배열 앞에 readonly 적용

let userInfo1 : UserInfo = [1, 'user1@example.com' , 'abcd123' , '1999-01-01' , true];

userInfo1.push('hello'); // Error
```

### any

어떤 값의 타입이 any이면 타입 검사를 실행하지 않음

### 함수

매개변수와 리턴값에 타입을 표기할 수 있음

```ts
// 매개변수 타입 표기
function greet(name: string) {
  console.log("Hello, " + name.toUpperCase() + "!!");
}

// 반환 타입 표기
function getFavoriteNumber(): number {
  return 26;
}
```

문맥을 통해 익명 함수의 타입을 추론할 수 있다면, 자동으로 타입이 부여됨

```ts
const names = ["Alice", "Bob", "Eve"];
 
names.forEach(function (s) {
  console.log(s.toUppercase());
  //Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
});
 
names.forEach((s) => {
  console.log(s.toUppercase());
  //Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
});
```

### 객체

```ts
let human: {
  name: string;
  age: number;
};

human = { name: '홍길동', age: 13 };
```

### Optional parameter

객체의 속성을 옵션화하거나 함수의 매개변수를 옵션화할 수 있음

```ts
function printName(obj: { first: string; last?: string }) {
  // ...
}
// 둘 다 OK
printName({ first: "Bob" });
printName({ first: "Alice", last: "Alisson" });
```

```ts
function greeting(name?: string): string {
  return `Hello, ${name || 'world'}`;
}
```

## Union vs. Intersection

기존의 타입을 기반으로 다양한 연산자를 사용해서 새로운 타입을 만들 수 있음

### Union Type

숫자 또는 문자를 받을 수 있는 함수

```ts
function printId(id: number | string) {
  console.log("Your ID is: " + id);
}
// OK
printId(101);
// OK
printId("202");
// 오류
printId({ myID: 22342 });
```

유니언을 사용할 때는 해당 유니언 타입의 모든 멤버에 대해 유효한 작업만 허용됨

`string | number` 유니언 타입의 경우, string 타입에만 유효한 메서드는 사용할 수 없음

```ts
function printId(id: number | string) {
  console.log(id.toUpperCase());
  // Property 'toUpperCase' does not exist on type 'string | number'.
  // Property 'toUpperCase' does not exist on type 'number'.
}
```

typeof를 이용해 분기 처리

```ts
function printId(id: number | string) {
  if (typeof id === "string") {
    // 이 분기에서 id는 'string' 타입을 가집니다
 
    console.log(id.toUpperCase());
  } else {
    // 여기에서 id는 'number' 타입을 가집니다
    console.log(id);
  }
}
```

### Intersection Type

여러 타입을 모두 만족하는 하나의 타입

```ts
interface Person {
  name: string;
  age: number;
}
interface Developer {
  name: string;
  skill: number;
}
type Capt = Person & Developer;
```

`Capt` 타입은 아래와 같이 정의됨

```ts
{
  name: string;
  age: number;
  skill: string;
}
```

## Type vs. Interface

### type

똑같은 타입을 재사용하거나 객체, 유니언 타입 등을 더 간단한 이름으로 부르고 싶은 경우 타입의 별칭을 만들 수 있음

```ts
type Point = {
  x: number;
  y: number;
};
 
function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}
 
printCoord({ x: 100, y: 100 });
```

```ts
type ID = number | string;
```

### interface

`type`과 마찬가지로 객체 타입을 만드는 또 다른 방법

```ts
interface Point {
  x: number;
  y: number;
}
 
function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}
 
printCoord({ x: 100, y: 100 });
```

### type과 interface의 차이점

인터페이스는 객체에만 사용되며, 원시타입에 이름을 부여하는 데는 사용할 수 없음

인터페이스는 `extends`를 통해 확장, 타입은 교집합을 통해 확장

```ts
interface Animal {
  name: string
}

interface Bear extends Animal {
  honey: boolean
}

const bear = getBear()
bear.name
bear.honey
```

```ts
type Animal = {
  name: string
}

type Bear = Animal & {
  honey: Boolean
}

const bear = getBear();
bear.name;
bear.honey;
```

인터페이스는 새 필드를 추가할 수 있지만, 타입은 생성한 뒤 달라질 수 없음

```ts
interface Window {
  title: string
}

interface Window {
  ts: TypeScriptAPI
}

const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});
```

```ts
type Window = {
  title: string
}

type Window = {
  ts: TypeScriptAPI
}

 // Error: Duplicate identifier 'Window'
```
