> For the complete documentation index, see [llms.txt](https://toktokhan.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://toktokhan.gitbook.io/docs/onborading/growing-up/ts-skill/extends.md).

# Extends

extends 는 typescript 에서 다양하게 사용이 가능합니다. 크게 아래와 같은 용도로 사용 됩니다.

* 확장
* 제한
* 조건부
* 추론 (with Infer)

## 타입의 확장

이름 그대로 interface 를 확장하고 싶을때 사용이 가능합니다. type 의 intersection(&) 문법과 동일한 기능입니다.

```typescript
type Profile = { name: string; age: number }
type DogProfile = Profile & { breed: 'Bulldog' | 'Poodle' };
// DogProfile { name: string; age:number; breed: 'Bulldog' | 'Poodle' }

interface DogProfile extends Profile {
    breed: 'Bulldog' | 'Poodle'
}
// DogProfile { name: string; age:number; breed: 'Bulldog' | 'Poodle' }

```

## Generic 의 타입 제한 하기

ts 함수의 인자 처럼 제너릭 타입을 제한 할수 있습니다.

```typescript
type MessageOf<T> = T["message"];
// Type Error: Type '"message"' cannot be used to index type 'T'.

type MessageOf<T extends { message: unknown }> = T["message"];

type Email = { message: string; }
type Chat = { text: string; }

type EmailMessage = MessageOf<Email>
type Email = MessageOf<Chat> // Type Error
```

위의 예시에서 첫번째 MessageOf 을 확인해 봅시다. 제너릭 T 의 타입은 정해지지 않았습니다. 따라서, property 에 message 가 없을 수 도 있기 때문에 에러가 발생 합니다.&#x20;

두번째 MessageOf 같은 경우는 extends 로 타입을 제한합니다. message property 를 가진 타입만 제너릭으로 들어올 수 있으므로, Error 가 발생하지 않습니다.&#x20;

반대로 제너릭을 사용할 때 옳지 않은 타입을 넘겨주면 Type Error 가 발생합니다.

{% embed url="<https://www.typescriptlang.org/ko/docs/handbook/2/generics.html#%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EC%95%BD%EC%A1%B0%EA%B1%B4-generic-constraints>" %}

## 조건부 타입

extends 는 많은 언어가 포함하고 있는 if 의 역할을 하기도 합니다.

```typescript
type Example = "A" extends string ? "STRING" : "UNKNOWN"; // "STRING"

// 제너릭에서 사용이 가능합니다.
type MessageOf<T> = T extends { message: unknown } ? T["message"] : never;

interface Email { message: string; } 
interface Dog { bark(): void; }
 
type EmailMessageContents = MessageOf<Email>; // string
type DogMessageContents = MessageOf<Dog>; // never           


// 중첩도 가능 합니다.
type TypeOf<T> = T extends string
  ? 'string'
  : T extends number
  ? 'number'
  : T extends boolean
  ? 'boolean'
  : 'unknown'

type StrType = TypeOf<string> // "string"
type StrType = TypeOf<number> // "string"
type StrType = TypeOf<Function> // "unknown"

```

## 타입 추론 Infer

아래와 같은 타입이 있다고 가정해봅시다. 우리는 때로 'User' 타입이 필요할 수 있습니다. 그럴땐 infer 키워드를 통해 타입을 추론 할 수 있습니다.

```typescript
const userList = [{ name: 'John' }] // type: Array<User>

type ItemOf<T> = T extends Array<infer U> ? U : unknown;
type User = ItemOf<typeof userList>; // User { name: string }
```

위에서 infer U 는 추론하고자 하는 타입을 의미합니다. 위의 ItemOf 를 문맥 그대로 해석해 봅시다.

제너릭 T 가 Array<추론하고자 하는 타입> 타입의 형태를 하고 있다면 ItemOf 의 반환 타입은 추론하고자 하는 타입이고, 아니면 unknown 이 라고 해석할 수 있습니다.
