<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>infp_pro.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Tue, 15 Jul 2025 09:37:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>infp_pro.log</title>
            <url>https://velog.velcdn.com/images/infp_pro/profile/33ec3a40-e6e8-45c9-a806-74f6a993ee73/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. infp_pro.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/infp_pro" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- Exclude, Extract, ReturnType (4)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Exclude-Extract-ReturnType-4</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Exclude-Extract-ReturnType-4</guid>
            <pubDate>Tue, 15 Jul 2025 09:37:56 GMT</pubDate>
            <description><![CDATA[<h2 id="excludet-k">Exclude&lt;T, K&gt;</h2>
<p>Exclude 타입은 다음과 같이 <code>T</code>로부터 <code>U</code>를 제거하는 타입임.</p>
<pre><code class="language-ts">type A = Exclude&lt;string | boolean, string&gt;;
// 결과: boolean</code></pre>
<p>직접 구현하면 다음과 같음.</p>
<pre><code class="language-ts">type Exclude&lt;T, U&gt; = T extends U ? never : T;</code></pre>
<hr>
<h2 id="extractt-k">Extract&lt;T, K&gt;</h2>
<p>Extract 타입은 다음과 같이 <code>T</code>로부터 <code>U</code>를 추출하는 타입임.</p>
<pre><code class="language-ts">type B = Extract&lt;string | boolean, boolean&gt;;
// 결과: boolean</code></pre>
<p>직접 구현하면 다음과 같음.</p>
<pre><code class="language-ts">type Extract&lt;T, U&gt; = T extends U ? T : never;</code></pre>
<hr>
<h2 id="returntypet">ReturnType<T></h2>
<p>ReturnType은 타입변수 <code>T</code>에 할당된 함수 타입의 반환값 타입을 추출하는 타입임. 이 타입은 <code>infer</code>를 활용해 구현할 수 있음.</p>
<pre><code class="language-ts">type ReturnType&lt;T extends (...args: any) =&gt; any&gt; = T extends (
  ...args: any
) =&gt; infer R
  ? R
  : never;</code></pre>
<h3 id="예시">예시</h3>
<pre><code class="language-ts">function funcA() {
  return &quot;hello&quot;;
}

function funcB() {
  return 10;
}

type ReturnA = ReturnType&lt;typeof funcA&gt;;
// 결과: string

type ReturnB = ReturnType&lt;typeof funcB&gt;;
// 결과: number</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- 
Record, Pick, Omit(3)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Record-Pick-Omit3</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Record-Pick-Omit3</guid>
            <pubDate>Tue, 15 Jul 2025 09:35:44 GMT</pubDate>
            <description><![CDATA[<h1 id="pickt-k">Pick&lt;T, K&gt;</h1>
<p><strong>Pick</strong>은 특정 객체 타입에서 일부 프로퍼티만 <strong>골라내는</strong> 유틸리티 타입임.</p>
<h2 id="예제">예제</h2>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const legacyPost: Pick&lt;Post, &quot;title&quot; | &quot;content&quot;&gt; = {
  title: &quot;&quot;,
  content: &quot;&quot;,
};</code></pre>
<h2 id="직접-구현">직접 구현</h2>
<pre><code class="language-ts">type Pick&lt;T, K extends keyof T&gt; = {
  [key in K]: T[key];
};</code></pre>
<hr>
<h1 id="omitt-k">Omit&lt;T, K&gt;</h1>
<p><strong>Omit</strong>은 특정 객체 타입에서 일부 프로퍼티만 <strong>제외하는</strong> 유틸리티 타입임.</p>
<h2 id="예제-1">예제</h2>
<pre><code class="language-ts">const noTitlePost: Omit&lt;Post, &quot;title&quot;&gt; = {
  content: &quot;&quot;,
  tags: [],
  thumbnailURL: &quot;&quot;,
};</code></pre>
<h2 id="직접-구현-1">직접 구현</h2>
<pre><code class="language-ts">type Omit&lt;T, K extends keyof T&gt; = Pick&lt;T, Exclude&lt;keyof T, K&gt;&gt;;</code></pre>
<hr>
<h1 id="recordk-v">Record&lt;K, V&gt;</h1>
<p><strong>Record</strong>는 키-값 쌍을 가지는 객체 타입을 생성할 때 사용함.</p>
<h2 id="예제-2">예제</h2>
<pre><code class="language-ts">type Thumbnail = Record&lt;
  &quot;large&quot; | &quot;medium&quot; | &quot;small&quot;,
  { url: string }
&gt;;</code></pre>
<h2 id="직접-구현-2">직접 구현</h2>
<pre><code class="language-ts">type Record&lt;K extends keyof any, V&gt; = {
  [key in K]: V;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- 
Partial, Required, Readonly(2)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Partial-Required-Readonly2</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Partial-Required-Readonly2</guid>
            <pubDate>Tue, 15 Jul 2025 09:33:40 GMT</pubDate>
            <description><![CDATA[<h1 id="맵드-타입-기반-유틸리티-타입">맵드 타입 기반 유틸리티 타입</h1>
<h2 id="선요약">선요약</h2>
<p>타입스크립트의 <code>Partial&lt;T&gt;</code>, <code>Required&lt;T&gt;</code>, <code>Readonly&lt;T&gt;</code>는 <strong>맵드 타입 기반의 유틸리티 타입</strong>으로, 객체 타입의 프로퍼티를 <strong>선택적</strong>, <strong>필수</strong>, <strong>읽기 전용</strong>으로 변환함. 이들은 <strong>제네릭 + keyof + 맵드 타입</strong>의 조합으로 구현할 수 있음.</p>
<hr>
<h2 id="partialt">Partial<T></h2>
<h3 id="목적">목적</h3>
<p>객체 타입의 <strong>모든 프로퍼티를 선택적(optional)</strong>으로 변환함.</p>
<h3 id="예시">예시</h3>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const draft: Partial&lt;Post&gt; = {
  title: &quot;제목 나중에 짓자&quot;,
  content: &quot;초안...&quot;,
};</code></pre>
<h3 id="구현">구현</h3>
<pre><code class="language-ts">type Partial&lt;T&gt; = {
  [key in keyof T]?: T[key];
};</code></pre>
<hr>
<h2 id="requiredt">Required<T></h2>
<h3 id="목적-1">목적</h3>
<p>객체 타입의 <strong>모든 프로퍼티를 필수(required)</strong>로 변환함.</p>
<h3 id="예시-1">예시</h3>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const withThumbnailPost: Required&lt;Post&gt; = {
  title: &quot;한입 타스 후기&quot;,
  tags: [&quot;ts&quot;],
  content: &quot;&quot;,
  thumbnailURL: &quot;https://...&quot;,
};</code></pre>
<h3 id="구현-1">구현</h3>
<pre><code class="language-ts">type Required&lt;T&gt; = {
  [key in keyof T]-?: T[key];
};</code></pre>
<hr>
<h2 id="readonlyt">Readonly<T></h2>
<h3 id="목적-2">목적</h3>
<p>객체 타입의 <strong>모든 프로퍼티를 읽기 전용(readonly)</strong>으로 변환함.</p>
<h3 id="예시-2">예시</h3>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const readonlyPost: Readonly&lt;Post&gt; = {
  title: &quot;보호된 게시글입니다.&quot;,
  tags: [],
  content: &quot;&quot;,
};

readonlyPost.content = &quot;해킹당함&quot;; // 오류 발생</code></pre>
<h3 id="구현-2">구현</h3>
<pre><code class="language-ts">type Readonly&lt;T&gt; = {
  readonly [key in keyof T]: T[key];
};</code></pre>
<hr>
<h2 id="마지막-요약">마지막 요약</h2>
<ul>
<li><code>Partial&lt;T&gt;</code>: 모든 프로퍼티를 선택적으로 만듦 (<code>?</code>).</li>
<li><code>Required&lt;T&gt;</code>: 모든 선택적 프로퍼티를 필수로 만듦 (<code>-?</code>).</li>
<li><code>Readonly&lt;T&gt;</code>: 모든 프로퍼티를 읽기 전용으로 만듦 (<code>readonly</code>).</li>
<li>이들 모두 <code>맵드 타입 + keyof + 제네릭</code> 조합으로 구현 가능함.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- 유틸리티 타입 소개(1)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%86%8C%EA%B0%9C1</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%86%8C%EA%B0%9C1</guid>
            <pubDate>Tue, 15 Jul 2025 09:31:46 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li>유틸리티 타입은 <strong>타입스크립트가 제공하는 특수한 타입 조합 도구</strong>임.</li>
<li>제네릭, 맵드 타입, 조건부 타입 등을 조합해 자주 쓰이는 형태의 타입을 미리 구현해둔 것임.</li>
<li>대표적인 유틸리티 타입으로는 <code>Readonly&lt;T&gt;</code>, <code>Partial&lt;T&gt;</code> 등이 있음.</li>
<li>이번 섹션에서는 이들 중 <strong>핵심적인 타입</strong>만 다루며, <strong>직접 구현</strong>도 병행함.</li>
</ul>
<hr>
<h2 id="유틸리티-타입-소개">유틸리티 타입 소개</h2>
<p>타입스크립트에서는 제네릭, 맵드 타입, 조건부 타입 등을 기반으로 실무에서 자주 사용되는 타입 조작 패턴을 미리 구현해둔 유틸리티 타입(Utility Types)을 제공함.</p>
<p>이들은 복잡한 타입을 <strong>짧고 직관적으로 표현</strong>하게 해 주며, <strong>타입 안전성과 생산성</strong>을 동시에 확보할 수 있음.</p>
<hr>
<h2 id="예시-1-readonlyt">예시 1: Readonly<T></h2>
<p><code>Readonly&lt;T&gt;</code>는 객체의 모든 프로퍼티를 <strong>읽기 전용(readonly)</strong>으로 변환함.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
}

const person: Readonly&lt;Person&gt; = {
  name: &quot;이정환&quot;,
  age: 27
};

person.name = &quot;&quot;; // ❌ 오류: 읽기 전용 프로퍼티</code></pre>
<hr>
<h2 id="예시-2-partialt">예시 2: Partial<T></h2>
<p><code>Partial&lt;T&gt;</code>는 객체의 모든 프로퍼티를 <strong>선택적(optional)</strong>으로 변환함.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
}

const person: Partial&lt;Person&gt; = {
  name: &quot;이정환&quot;
};
// age는 생략 가능</code></pre>
<hr>
<h2 id="유틸리티-타입의-핵심">유틸리티 타입의 핵심</h2>
<p>타입스크립트는 수십 가지 유틸리티 타입을 기본 제공함. 그중 자주 쓰이는 타입들부터 숙지하면 실무 적용에 큰 도움이 됨.</p>
<p>공식 문서:
👉 <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html">https://www.typescriptlang.org/docs/handbook/utility-types.html</a></p>
<hr>
<h2 id="학습-방향">학습 방향</h2>
<p>이번 섹션에서는 다음과 같은 방향으로 진행함:</p>
<ul>
<li><strong>맵드 타입 기반 유틸리티 타입</strong>: <code>Readonly&lt;T&gt;</code>, <code>Partial&lt;T&gt;</code> 등</li>
<li><strong>조건부 타입 기반 유틸리티 타입</strong>: <code>Exclude&lt;T, U&gt;</code>, <code>Extract&lt;T, U&gt;</code> 등</li>
<li><strong>직접 구현</strong>을 통해 유틸리티 타입의 원리와 작동 방식 이해</li>
</ul>
<hr>
<h2 id="🧾-마지막-요약">🧾 마지막 요약</h2>
<ul>
<li>유틸리티 타입은 타입 조작 기능의 집약체로, 복잡한 타입을 효율적으로 다룰 수 있게 함.</li>
<li>대표적인 타입으로 <code>Readonly</code>, <code>Partial</code>, <code>Exclude</code>, <code>ReturnType</code> 등이 있음.</li>
<li>다음 시간부터 실전 유틸리티 타입 구현을 병행하여 <strong>타입스크립트 고급 문법 숙련도</strong>를 높일 예정임.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션9. 조건부 타입- infer(2)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-infer2</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-infer2</guid>
            <pubDate>Tue, 15 Jul 2025 09:29:22 GMT</pubDate>
            <description><![CDATA[<h2 id="🧷-선요약">🧷 선요약</h2>
<ul>
<li><code>infer</code>는 조건부 타입 안에서 특정 타입을 추론할 수 있게 해주는 타입스크립트의 특수 문법임.</li>
<li><code>infer</code>는 보통 조건부 타입 내부에서 사용되며, 추론 가능한 타입이 있을 경우 해당 타입을 바탕으로 분기된 타입 결과를 생성함.</li>
<li>대표적인 활용 예시로는 <code>ReturnType&lt;T&gt;</code> 과 <code>PromiseUnpack&lt;T&gt;</code> 등의 유틸리티 타입 구현이 있음.</li>
</ul>
<hr>
<h2 id="infer로-returntypet-구현하기">infer로 ReturnType<T> 구현하기</h2>
<pre><code class="language-ts">type ReturnType&lt;T&gt; = T extends () =&gt; infer R ? R : never;</code></pre>
<p><code>infer R</code>은 함수 타입 <code>T</code>의 반환값을 추론해 <code>R</code>로 잡겠다는 의미임. 예시를 보자.</p>
<pre><code class="language-ts">type FuncA = () =&gt; string;
type FuncB = () =&gt; number;

type A = ReturnType&lt;FuncA&gt;; // string
type B = ReturnType&lt;FuncB&gt;; // number</code></pre>
<p>타입 변수 <code>T</code>에 함수 타입을 넣으면 해당 함수의 반환값 타입을 <code>infer R</code>이 추론하게 됨.<br>즉 <code>FuncA</code>는 <code>() =&gt; string</code> 타입이므로 <code>R</code>은 <code>string</code>이 되고, 따라서 <code>A</code>는 <code>string</code> 타입이 됨.</p>
<h3 id="추론-실패-시">추론 실패 시</h3>
<pre><code class="language-ts">type C = ReturnType&lt;number&gt;; // never</code></pre>
<p>이 경우에는 <code>number</code> 타입은 함수 타입이 아니므로 조건식을 만족하지 않음.<br>결과적으로 <code>ReturnType&lt;number&gt;</code>는 <code>never</code> 타입이 됨.</p>
<hr>
<h2 id="infer로-promise의-결과-타입-추출하기">infer로 Promise의 결과 타입 추출하기</h2>
<pre><code class="language-ts">type PromiseUnpack&lt;T&gt; = T extends Promise&lt;infer R&gt; ? R : never;</code></pre>
<p><code>PromiseUnpack</code>은 <code>Promise&lt;T&gt;</code> 타입으로부터 내부의 <code>T</code> 타입을 꺼내오는 유틸리티 타입임.</p>
<p>예시:</p>
<pre><code class="language-ts">type PromiseA = PromiseUnpack&lt;Promise&lt;number&gt;&gt;; // number
type PromiseB = PromiseUnpack&lt;Promise&lt;string&gt;&gt;; // string</code></pre>
<p><code>infer R</code>을 통해 <code>Promise&lt;number&gt;</code>는 <code>number</code> 타입이 추론되고, 최종적으로 <code>PromiseUnpack&lt;Promise&lt;number&gt;&gt;</code>는 <code>number</code>가 됨.</p>
<hr>
<h2 id="🧩-마지막-요약">🧩 마지막 요약</h2>
<ul>
<li><code>infer</code>는 조건부 타입 내에서 특정 타입을 <strong>추론</strong>할 때 사용함.</li>
<li>일반적으로 유틸리티 타입에서 많이 활용됨 (예: ReturnType, Parameters, PromiseUnpack 등).</li>
<li>조건식이 성립하지 않으면 <code>never</code> 타입으로 수렴됨.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션9. 조건부 타입- 분산적인 조건부 타입(1)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EB%B6%84%EC%82%B0%EC%A0%81%EC%9D%B8-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%851</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EB%B6%84%EC%82%B0%EC%A0%81%EC%9D%B8-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%851</guid>
            <pubDate>Tue, 15 Jul 2025 09:24:42 GMT</pubDate>
            <description><![CDATA[<h1 id="분산적인-조건부-타입">분산적인 조건부 타입</h1>
<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li>조건부 타입에 유니온 타입을 넣으면 각 요소에 대해 조건이 개별로 평가되는 <strong>분산 조건부 타입</strong>이 작동함.</li>
<li>이를 이용해 <code>Exclude</code>, <code>Extract</code> 등 다양한 유틸리티 타입을 직접 구현 가능함.</li>
</ul>
<hr>
<h2 id="조건부-타입-복습">조건부 타입 복습</h2>
<pre><code class="language-ts">type StringNumberSwitch&lt;T&gt; = T extends number ? string : number;

let a: StringNumberSwitch&lt;number&gt;;  // string
let b: StringNumberSwitch&lt;string&gt;;  // number</code></pre>
<hr>
<h2 id="분산-조건부-타입의-등장">분산 조건부 타입의 등장</h2>
<pre><code class="language-ts">type StringNumberSwitch&lt;T&gt; = T extends number ? string : number;

let c: StringNumberSwitch&lt;number | string&gt;; 
// 결과: string | number</code></pre>
<h3 id="❓-왜-이런-결과가-나옴">❓ 왜 이런 결과가 나옴?</h3>
<ul>
<li>조건부 타입의 타입 변수에 <strong>Union 타입</strong>이 들어가면, 조건이 <strong>각 요소별로 분리</strong>되어 평가됨.</li>
<li>이를 <strong>분산 조건부 타입</strong>이라 함.</li>
</ul>
<h3 id="분산-과정">분산 과정:</h3>
<ol>
<li><p>타입 분해:</p>
<pre><code class="language-ts">StringNumberSwitch&lt;number&gt;     // string
StringNumberSwitch&lt;string&gt;     // number</code></pre>
</li>
<li><p>결과 결합:</p>
<pre><code class="language-ts">string | number</code></pre>
</li>
</ol>
<hr>
<h2 id="exclude-조건부-타입-구현">Exclude 조건부 타입 구현</h2>
<pre><code class="language-ts">type Exclude&lt;T, U&gt; = T extends U ? never : T;

type A = Exclude&lt;number | string | boolean, string&gt;; 
// 결과: number | boolean</code></pre>
<h3 id="계산-흐름">계산 흐름:</h3>
<ol>
<li><p>타입 분리:</p>
<pre><code class="language-ts">Exclude&lt;number, string&gt;   // number
Exclude&lt;string, string&gt;   // never
Exclude&lt;boolean, string&gt;  // boolean</code></pre>
</li>
<li><p>결과 결합:</p>
<pre><code class="language-ts">number | never | boolean → number | boolean</code></pre>
</li>
</ol>
<blockquote>
<p><code>never</code>는 공집합이므로 Union에서 자동 제거됨</p>
</blockquote>
<hr>
<h2 id="🧠-마지막-요약">🧠 마지막 요약</h2>
<ul>
<li>조건부 타입에 유니온을 전달하면 <strong>자동으로 분산 평가</strong>됨.</li>
<li>이를 활용하면 타입 연산에서 필터링, 매핑 같은 고급 기능을 구현할 수 있음.</li>
<li><code>Exclude&lt;T, U&gt;</code>는 T에서 U에 해당하는 타입만 제거함.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션9. 조건부 타입- 조건부 타입(0)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%850</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%850</guid>
            <pubDate>Tue, 15 Jul 2025 09:22:09 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<p>조건부 타입은 <code>extends</code>와 삼항 연산자(<code>? :</code>)를 활용해 타입을 상황에 따라 다르게 설정할 수 있게 해줌. 특히 제네릭과 함께 사용할 때 매우 강력하며, 값의 타입에 따라 반환 타입을 유연하게 조절할 수 있음. 타입스크립트의 타입 로직에 논리적 분기를 넣을 수 있다는 점이 핵심임.</p>
<hr>
<h2 id="1-조건부-타입-기본-문법">1. 조건부 타입 기본 문법</h2>
<pre><code class="language-ts">type A = number extends string ? number : string; 
// A → string</code></pre>
<p>number가 string의 서브타입인지 여부에 따라 결과가 달라짐. 위 예시는 false가 되어 A는 <code>string</code>이 됨.</p>
<pre><code class="language-ts">type ObjA = { a: number };
type ObjB = { a: number; b: number };

type B = ObjB extends ObjA ? number : string;
// B → number (ObjB는 ObjA의 슈퍼셋)</code></pre>
<hr>
<h2 id="2-제네릭-조건부-타입">2. 제네릭 조건부 타입</h2>
<pre><code class="language-ts">type StringNumberSwitch&lt;T&gt; = T extends number ? string : number;

let varA: StringNumberSwitch&lt;number&gt;; // string
let varB: StringNumberSwitch&lt;string&gt;; // number</code></pre>
<p>타입 변수 <code>T</code>가 number면 결과는 string, 아니면 number가 됨.</p>
<hr>
<h2 id="3-조건부-타입-실전-예제">3. 조건부 타입 실전 예제</h2>
<pre><code class="language-ts">function removeSpaces&lt;T&gt;(text: T): T extends string ? string : undefined {
  if (typeof text === &quot;string&quot;) {
    return text.replaceAll(&quot; &quot;, &quot;&quot;) as any;
  } else {
    return undefined as any;
  }
}</code></pre>
<ul>
<li><code>removeSpaces(&quot;hello world&quot;)</code> → string</li>
<li><code>removeSpaces(undefined)</code> → undefined</li>
</ul>
<p>하지만 위 방식은 <code>as any</code> 때문에 타입 안정성이 깨질 수 있음. 예를 들어 string이 아닌 값을 반환해도 타입 검사를 통과함.</p>
<hr>
<h2 id="4-함수-오버로딩으로-해결">4. 함수 오버로딩으로 해결</h2>
<pre><code class="language-ts">function removeSpaces&lt;T&gt;(text: T): T extends string ? string : undefined;
function removeSpaces(text: any) {
  if (typeof text === &quot;string&quot;) {
    return text.replaceAll(&quot; &quot;, &quot;&quot;);
  } else {
    return undefined;
  }
}

let result = removeSpaces(&quot;hi im winterlood&quot;); // string
let result2 = removeSpaces(undefined);         // undefined</code></pre>
<p>오버로딩을 사용하면 조건부 타입의 결과를 실제로 타입스크립트가 추론할 수 있게 되므로, <code>as any</code> 없이도 타입 안정성을 확보할 수 있음.</p>
<hr>
<h2 id="🔁-마지막-정리">🔁 마지막 정리</h2>
<ul>
<li>조건부 타입은 타입에 <code>if-else</code> 같은 논리를 넣을 수 있게 해주는 기능임.</li>
<li><code>A extends B ? C : D</code> 형식으로 작성하며, 특히 제네릭과 함께 강력함.</li>
<li><code>as any</code>보다는 <strong>함수 오버로딩</strong>을 통한 추론이 더 안전하고 실용적임.</li>
<li>실제 사용 예시로 입력 타입에 따라 다른 반환 타입을 가질 수 있는 함수를 구현할 수 있음.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-
템플릿 리터럴 타입(4)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A6%AC%ED%84%B0%EB%9F%B4-%ED%83%80%EC%9E%854</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A6%AC%ED%84%B0%EB%9F%B4-%ED%83%80%EC%9E%854</guid>
            <pubDate>Tue, 15 Jul 2025 09:19:22 GMT</pubDate>
            <description><![CDATA[<h1 id="템플릿-리터럴-타입">템플릿 리터럴 타입</h1>
<h2 id="선요약">선요약</h2>
<p>템플릿 리터럴 타입은 문자열 패턴을 조합해 새로운 문자열 리터럴 유니온 타입을 만드는 타입스크립트의 타입 조작 기능임. 여러 문자열 유니온 타입을 조합할 때 반복적인 수작업 없이 효율적으로 조합 가능함.</p>
<hr>
<h2 id="템플릿-리터럴-타입이란">템플릿 리터럴 타입이란?</h2>
<p>템플릿 리터럴 타입은 타입 조작 기능 중 가장 단순한 기능으로, 템플릿 리터럴 문법을 이용해 특정 <strong>패턴을 갖는 문자열 타입</strong>을 만드는 기능임.</p>
<pre><code class="language-ts">type Color = &quot;red&quot; | &quot;black&quot; | &quot;green&quot;;
type Animal = &quot;dog&quot; | &quot;cat&quot; | &quot;chicken&quot;;</code></pre>
<p>위와 같은 코드에서 아래와 같이 모든 조합의 문자열 리터럴 타입을 만들고 싶다고 가정함:</p>
<pre><code class="language-ts">type ColoredAnimal =
  | &quot;red-dog&quot;
  | &quot;red-cat&quot;
  | &quot;red-chicken&quot;
  | &quot;black-dog&quot;
  | &quot;black-cat&quot;
  | &quot;black-chicken&quot;
  | &quot;green-dog&quot;
  | &quot;green-cat&quot;
  | &quot;green-chicken&quot;;</code></pre>
<p>위처럼 수작업으로 만들면 타입이 늘어날수록 불편하고 오류 가능성도 커짐. 이럴 때 템플릿 리터럴 타입을 쓰면 다음처럼 간단하게 표현 가능함:</p>
<pre><code class="language-ts">type ColoredAnimal = `${Color}-${Animal}`;</code></pre>
<ul>
<li><code>Color</code>의 모든 값과 <code>Animal</code>의 모든 값을 문자열로 조합한 유니온 타입이 자동으로 생성됨</li>
<li><code>${}</code> 안에는 타입 변수 또는 타입 이름을 넣을 수 있음</li>
</ul>
<hr>
<h2 id="예시-응용">예시 응용</h2>
<h3 id="특정-접두어-붙이기">특정 접두어 붙이기</h3>
<pre><code class="language-ts">type Prefix = &quot;pre&quot;;
type Word = &quot;load&quot; | &quot;view&quot;;

type PrefixedWord = `${Prefix}_${Word}`;
// &quot;pre_load&quot; | &quot;pre_view&quot;</code></pre>
<h3 id="이벤트-핸들러-이름-만들기">이벤트 핸들러 이름 만들기</h3>
<pre><code class="language-ts">type Event = &quot;click&quot; | &quot;hover&quot;;
type HandlerName = `on${Capitalize&lt;Event&gt;}`;
// &quot;onClick&quot; | &quot;onHover&quot;</code></pre>
<ul>
<li><code>Capitalize&lt;T&gt;</code>: 첫 글자를 대문자로 바꿔줌</li>
<li><code>Uncapitalize&lt;T&gt;</code>: 첫 글자를 소문자로 바꿔줌</li>
<li><code>Uppercase&lt;T&gt;</code>, <code>Lowercase&lt;T&gt;</code>: 대문자화, 소문자화</li>
</ul>
<hr>
<h2 id="주의사항">주의사항</h2>
<ul>
<li>템플릿 리터럴 타입은 <strong>컴파일 타임</strong>에 조합됨 → 런타임에는 영향을 주지 않음</li>
<li><code>${}</code> 내부에 값(value)을 넣는 것이 아니라 <strong>타입</strong>을 넣는 것임</li>
<li>리터럴 유니온 타입이 너무 많아지면 타입 추론이 느려질 수 있음</li>
</ul>
<hr>
<h2 id="마지막-요약">마지막 요약</h2>
<p>템플릿 리터럴 타입은 문자열 리터럴 조합을 자동화하여, 복잡한 유니온 타입을 간결하고 안전하게 생성할 수 있게 해주는 타입스크립트의 문법임. 반복적인 문자열 타입 정의를 줄이고, 패턴 기반의 타입 생성이 필요한 상황에서 특히 유용함.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-맵드 타입(3)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EB%A7%B5%EB%93%9C-%ED%83%80%EC%9E%853</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EB%A7%B5%EB%93%9C-%ED%83%80%EC%9E%853</guid>
            <pubDate>Tue, 15 Jul 2025 09:16:52 GMT</pubDate>
            <description><![CDATA[<h1 id="맵드-타입-mapped-types">맵드 타입 (Mapped Types)</h1>
<h2 id="요약">요약</h2>
<p>맵드 타입(mapped type)은 기존 객체 타입을 기반으로 <strong>새로운 객체 타입을 유연하게 생성</strong>할 수 있는 타입스크립트의 기능임. <code>keyof</code>, 인덱스드 엑세스 타입 등과 결합해 중복 없이 코드를 간결하게 유지할 수 있음.</p>
<hr>
<h2 id="기본-예시">기본 예시</h2>
<pre><code class="language-ts">interface User {
  id: number;
  name: string;
  age: number;
}

// 수정 가능한 필드를 선택적으로 만들고 싶을 때
type PartialUser = {
  [key in &quot;id&quot; | &quot;name&quot; | &quot;age&quot;]?: User[key];
};</code></pre>
<p>이 맵드 타입은 다음과 같은 결과 타입이 됨:</p>
<pre><code class="language-ts">{
  id?: number;
  name?: string;
  age?: number;
}</code></pre>
<hr>
<h2 id="keyof와-결합">&#39;keyof`와 결합</h2>
<pre><code class="language-ts">type PartialUser = {
  [key in keyof User]?: User[key];
};</code></pre>
<p><code>keyof User</code>는 <code>&quot;id&quot; | &quot;name&quot; | &quot;age&quot;</code>와 같기 때문에 위와 동일한 결과 타입이 생성됨.</p>
<hr>
<h2 id="읽기-전용-타입-만들기">읽기 전용 타입 만들기</h2>
<pre><code class="language-ts">type ReadonlyUser = {
  readonly [key in keyof User]: User[key];
};</code></pre>
<p>→ 모든 프로퍼티를 <code>readonly</code>로 변환한 새 타입이 생성됨.</p>
<hr>
<h2 id="활용-예시">활용 예시</h2>
<p>기존 타입을 기반으로:</p>
<ul>
<li>모든 프로퍼티를 <strong>선택적(optional)</strong> 으로 만들거나,</li>
<li>모든 프로퍼티를 <strong>읽기 전용(readonly)</strong> 으로 만들거나,</li>
<li>특정 키만 골라서 <strong>부분적으로 정의된 타입</strong>을 만들 수 있음.</li>
</ul>
<p>이러한 방식으로 유지보수와 확장성이 매우 뛰어난 타입 정의가 가능해짐.</p>
<hr>
<h2 id="요약-정리">요약 정리</h2>
<ul>
<li>맵드 타입은 반복되는 타입 정의를 <strong>자동화</strong>함</li>
<li><code>keyof</code>, 인덱스드 엑세스 타입 등과 함께 사용하면 <strong>강력한 타입 변환기</strong>가 됨</li>
<li><strong>실무에서 자주 사용</strong>되는 패턴임 (<code>Partial</code>, <code>Readonly</code>, <code>Pick</code>, <code>Record</code> 등이 전부 맵드 타입으로 구현되어 있음)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-keyof & typeof 연산자(2)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-keyof-typeof-%EC%97%B0%EC%82%B0%EC%9E%902</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-keyof-typeof-%EC%97%B0%EC%82%B0%EC%9E%902</guid>
            <pubDate>Tue, 15 Jul 2025 08:29:26 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<ul>
<li><code>keyof</code> 연산자는 객체 타입에서 모든 프로퍼티 키를 문자열 리터럴 유니온 타입으로 추출함.</li>
<li>수동으로 <code>&quot;name&quot; | &quot;age&quot;</code> 같은 키 목록을 명시하지 않고, 타입에서 자동 추출할 수 있어 유지보수에 용이함.</li>
<li><code>keyof</code>는 타입에만 적용 가능하며, 값에는 사용할 수 없음.</li>
<li><code>typeof</code>와 함께 사용하면 실제 변수의 타입 구조로부터 키를 추출하는 것도 가능함.</li>
</ul>
<hr>
<h1 id="keyof-연산자">Keyof 연산자</h1>
<p><code>keyof</code> 연산자는 객체 타입으로부터 프로퍼티의 모든 key들을 String Literal Union 타입으로 추출하는 연산자임.</p>
<p>다음은 <code>keyof</code> 연산자를 사용하는 예시임.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
}

function getPropertyKey(person: Person, key: &quot;name&quot; | &quot;age&quot;) {
  return person[key];
}</code></pre>
<p>이렇게 키를 명시하면 Person 타입이 바뀔 때마다 <code>&quot;name&quot; | &quot;age&quot;</code>를 함께 바꿔줘야 하는 번거로움이 생김.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
  location: string; // 추가됨
}

function getPropertyKey(person: Person, key: &quot;name&quot; | &quot;age&quot; | &quot;location&quot;) {
  return person[key];
}</code></pre>
<p>이럴 때 <code>keyof</code> 연산자를 쓰면 유지보수가 쉬워짐.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
  location: string;
}

function getPropertyKey(person: Person, key: keyof Person) {
  return person[key];
}</code></pre>
<p><code>keyof Person</code>의 결과는 <code>&quot;name&quot; | &quot;age&quot; | &quot;location&quot;</code>이 됨.</p>
<p>주의할 점: <code>keyof</code>는 <strong>값</strong>이 아닌 <strong>타입</strong>에만 적용할 수 있음.</p>
<pre><code class="language-ts">function getPropertyKey(person: Person, key: keyof person) { // ❌ 오류
  return person[key];
}</code></pre>
<hr>
<h1 id="typeof와-keyof-함께-사용하기">Typeof와 Keyof 함께 사용하기</h1>
<p><code>typeof</code> 연산자는 값을 기반으로 타입을 추론할 수 있게 해주는 타입스크립트의 기능임.</p>
<pre><code class="language-ts">const person = {
  name: &quot;이정환&quot;,
  age: 27,
  location: &quot;서울&quot;
};

type Person = typeof person;
// Person 타입은 { name: string; age: number; location: string }이 됨</code></pre>
<p>이걸 활용해 <code>keyof</code>와 함께 쓰면 다음과 같이 사용 가능함.</p>
<pre><code class="language-ts">function getPropertyKey(person: typeof person, key: keyof typeof person) {
  return person[key];
}</code></pre>
<p>이렇게 하면 <strong>변수의 구조에 따라 자동으로 키 타입이 추출되므로</strong> 더 안정적이고 유연한 타입 선언이 가능함.</p>
<hr>
<h1 id="마지막-요약">마지막 요약</h1>
<ul>
<li><code>keyof</code>는 타입으로부터 프로퍼티 키들을 추출해 유니온 타입으로 만듦.</li>
<li><code>typeof</code>는 변수로부터 타입을 추론함.</li>
<li>둘을 함께 사용하면 유지보수와 타입 안정성을 모두 챙길 수 있음.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-인덱스드 엑세스 타입(1)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EB%93%9C-%EC%97%91%EC%84%B8%EC%8A%A4-%ED%83%80%EC%9E%851</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EB%93%9C-%EC%97%91%EC%84%B8%EC%8A%A4-%ED%83%80%EC%9E%851</guid>
            <pubDate>Tue, 15 Jul 2025 08:25:31 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<ul>
<li>인덱스드 엑세스 타입은 객체, 배열, 튜플에서 특정 속성의 타입을 추출할 때 사용함.</li>
<li>문법은 <code>타입명[&quot;프로퍼티명&quot;]</code> 또는 <code>타입명[숫자]</code> 형태로 사용함.</li>
<li>객체 속성 변경 시 매개변수 타입도 자동 반영 가능함.</li>
<li>유효하지 않은 인덱스 사용 시 오류 발생함.</li>
<li>배열/튜플의 요소 타입을 추출하여 재사용하거나 제네릭화할 수 있음.</li>
</ul>
<hr>
<h1 id="인덱스드-엑세스-타입">인덱스드 엑세스 타입</h1>
<p>인덱스드 엑세스 타입은 인덱스를 이용해 다른 타입내의 특정 프로퍼티의 타입을 추출하는 타입임. 객체, 배열, 튜플에 모두 사용할 수 있음.</p>
<h2 id="객체-프로퍼티의-타입-추출">객체 프로퍼티의 타입 추출</h2>
<pre><code class="language-ts">interface Post {
  title: string;
  content: string;
  author: {
    id: number;
    name: string;
    age: number;
  };
}

function printAuthorInfo(author: Post[&quot;author&quot;]) {
  console.log(`${author.id} - ${author.name}`);
}</code></pre>
<ul>
<li><code>Post[&quot;author&quot;]</code>는 <code>Post</code> 타입에서 <code>author</code> 프로퍼티의 타입을 추출함.</li>
<li>인덱스는 <strong>문자열 리터럴 타입</strong>만 가능하며, 변수 사용은 불가함.</li>
</ul>
<pre><code class="language-ts">const authorKey = &quot;author&quot;;
function printAuthorInfo(author: Post[authorKey]) { // ❌ 오류 발생
  console.log(`${author.id} - ${author.name}`);
}</code></pre>
<ul>
<li>존재하지 않는 프로퍼티에 접근하려고 하면 오류 발생함.</li>
</ul>
<p>중첩 접근도 가능함.</p>
<pre><code class="language-ts">function printAuthorInfo(authorId: Post[&quot;author&quot;][&quot;id&quot;]) {
  console.log(authorId);
}</code></pre>
<h2 id="배열-요소-타입-추출">배열 요소 타입 추출</h2>
<pre><code class="language-ts">type PostList = Post[];
const post: PostList[number] = {
  title: &quot;게시글 제목&quot;,
  content: &quot;게시글 본문&quot;,
  author: {
    id: 1,
    name: &quot;이정환&quot;,
    age: 27,
  },
};</code></pre>
<ul>
<li><code>PostList[number]</code>는 배열의 요소 타입을 추출함.</li>
<li><code>PostList[0]</code>처럼 숫자 리터럴을 써도 동일하게 동작함.</li>
</ul>
<h2 id="튜플의-요소-타입-추출">튜플의 요소 타입 추출</h2>
<pre><code class="language-ts">type Tup = [number, string, boolean];

type Tup0 = Tup[0]; // number
type Tup1 = Tup[1]; // string
type Tup2 = Tup[2]; // boolean
type Tup3 = Tup[number]; // number | string | boolean</code></pre>
<ul>
<li>튜플에 <code>number</code> 인덱스를 넣으면 모든 요소의 유니온 타입이 추출됨.</li>
</ul>
<hr>
<h1 id="요약">요약</h1>
<ul>
<li>인덱스드 엑세스 타입은 객체나 배열/튜플에서 타입을 추출하여 재사용할 때 유용함.</li>
<li>중복 정의를 피하고 타입 변화에 유연하게 대응할 수 있음.</li>
<li>배열 요소 타입은 <code>[number]</code>, 튜플은 <code>[숫자]</code> 또는 <code>[number]</code>로 유니온 처리됨.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-타입 조작이란(0)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%EC%9D%B4%EB%9E%800</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%EC%9D%B4%EB%9E%800</guid>
            <pubDate>Tue, 15 Jul 2025 08:21:00 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<p>타입스크립트에서 타입 조작이란 기존 타입(기본 타입, 인터페이스, 타입 별칭 등)을 상황에 따라 동적으로 변형하는 기능을 의미함. 주요 도구로는 인덱스드 엑세스 타입, keyof 타입, 맵드 타입, 템플릿 리터럴 타입 등이 있으며, 제네릭 또한 타입 조작의 일부로 볼 수 있음. 이 기능들은 실무에서 유용하게 사용되며, 코드의 재사용성과 유연성을 크게 향상시킴.</p>
<hr>
<h1 id="타입-조작이란">타입 조작이란</h1>
<p>타입을 조작한다는 것은 기존의 기본 타입이나 별칭, 인터페이스로 만들어진 타입들을 상황에 따라 유동적으로 다른 타입으로 변형하는 기능임. 이는 타입스크립트의 강력하고 독특한 기능 중 하나임.</p>
<p>이전에 배운 제네릭 또한 함수나 인터페이스, 타입 별칭, 클래스 등에 적용해서 상황에 따라 달라지는 타입을 정의할 수 있기 때문에 타입 조작 기능의 일종임. 다만 그 내용이 방대해 따로 분리해 학습했음.</p>
<p>타입스크립트는 제네릭 외에도 여러가지 타입 조작 기능을 제공함. 이번 섹션에서는 제네릭과 다음에 다룰 조건부 타입을 제외한 4가지 대표적 타입 조작 기능을 정리함:
<img src="https://velog.velcdn.com/images/infp_pro/post/26bb41ba-8a6c-4158-9c63-bfe7b17b7212/image.png" alt=""></p>
<hr>
<h2 id="1-인덱스드-엑세스-타입">1. 인덱스드 엑세스 타입</h2>
<p>객체, 배열, 튜플 등의 타입에서 특정 프로퍼티나 요소의 타입만 추출할 수 있게 함.<br>예시: <code>type NameType = User[&quot;name&quot;]</code> → User 타입의 name 프로퍼티 타입만 따로 추출함.
<img src="https://velog.velcdn.com/images/infp_pro/post/3b4d56d7-f8c6-4909-9a46-f12847d745c0/image.png" alt=""></p>
<hr>
<h2 id="2-keyof-타입">2. keyof 타입</h2>
<p>객체 타입 내의 프로퍼티 이름들을 문자열 리터럴 유니온 타입으로 추출함.<br>예시: <code>type UserKeys = keyof User</code> → &quot;name&quot; | &quot;age&quot; | &quot;email&quot; 같은 유니온 타입이 됨.
<img src="https://velog.velcdn.com/images/infp_pro/post/94637a22-4a23-4deb-858c-9de5a30650f4/image.png" alt=""></p>
<hr>
<h2 id="3-맵드-타입">3. 맵드 타입</h2>
<p>기존 객체 타입을 기반으로 새로운 객체 타입을 정의함. 자바스크립트의 map 함수와 유사한 역할을 함.<br>예시: 모든 프로퍼티를 optional 하게 바꾸는 타입을 정의할 수 있음.<br><code>type Partial&lt;T&gt; = { [P in keyof T]?: T[P] }</code>
<img src="https://velog.velcdn.com/images/infp_pro/post/c37f1fbc-38ea-4f0f-9fff-4538354baf6e/image.png" alt=""></p>
<hr>
<h2 id="4-템플릿-리터럴-타입">4. 템플릿 리터럴 타입</h2>
<p>기존 문자열 리터럴 타입을 기반으로 정해진 패턴의 문자열만 포함하는 타입을 만들 수 있음.<br>예시:<br><code>type Color = &quot;red&quot; | &quot;blue&quot;</code><br><code>type BrightColor = \</code>bright-${Color}`<code>→ &quot;bright-red&quot; | &quot;bright-blue&quot;</code>
<img src="blob:https://velog.io/2faee308-5fb2-42b7-983f-ee2af18ca924" alt="업로드중.."></p>
<hr>
<p>이러한 기능들은 단순한 문법 외에도, 실무에서 어떤 상황에 이 기능을 써야 효과적인지를 이해하는 것이 중요함. 각 기능들은 심플하지만 실전에서 자주 쓰일 수 있는 예제들과 함께 학습할 예정임.</p>
<hr>
<h1 id="요약">요약</h1>
<ul>
<li>타입 조작이란 기존 타입들을 변형하여 새로운 타입을 만들어내는 기능임.</li>
<li>대표적 조작 도구: 인덱스드 엑세스 타입, keyof, 맵드 타입, 템플릿 리터럴 타입.</li>
<li>제네릭도 타입 조작의 일종으로 간주함.</li>
<li>이런 기능들은 코드의 유연성, 재사용성, 안전성을 높이는데 매우 유용함.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-프로미스와 제네릭(6)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4%EC%99%80-%EC%A0%9C%EB%84%A4%EB%A6%AD6</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4%EC%99%80-%EC%A0%9C%EB%84%A4%EB%A6%AD6</guid>
            <pubDate>Tue, 15 Jul 2025 08:16:41 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<ul>
<li><code>Promise&lt;T&gt;</code>는 제네릭 클래스로, <code>resolve</code>의 결과값 타입을 <code>T</code>로 설정할 수 있다.</li>
<li><code>reject</code>의 값은 타입을 지정할 수 없으며, 기본적으로 <code>unknown</code>이다.</li>
<li><code>then()</code> 메서드는 <code>resolve</code> 값을, <code>catch()</code> 메서드는 <code>reject</code> 값을 다룬다.</li>
<li>함수의 반환 타입으로 <code>Promise&lt;타입&gt;</code>을 명시하여 비동기 작업의 결과 타입을 선언할 수 있다.</li>
</ul>
<hr>
<h1 id="promise-사용하기">Promise 사용하기</h1>
<p><code>Promise</code>는 제네릭 클래스로 구현되어 있다. 따라서 새로운 <code>Promise</code>를 생성할 때 다음과 같이 타입 변수에 할당할 타입을 직접 설정해 주면 해당 타입이 바로 <code>resolve</code> 결과값의 타입이 됨.</p>
<pre><code class="language-ts">const promise = new Promise&lt;number&gt;((resolve, reject) =&gt; {
  setTimeout(() =&gt; {
    // 결과값 : 20
    resolve(20);
  }, 3000);
});

promise.then((response) =&gt; {
  // response는 number 타입
  console.log(response);
});

promise.catch((error) =&gt; {
  if (typeof error === &quot;string&quot;) {
    console.log(error);
  }
});</code></pre>
<blockquote>
<p>❗ <code>reject</code> 함수에 전달된 값의 타입은 지정할 수 없고, 타입스크립트에서는 기본적으로 <code>unknown</code>으로 처리되므로, <code>catch</code>에서 타입 좁히기를 통해 안전하게 다뤄야 함.</p>
</blockquote>
<h2 id="함수에서-promise-반환">함수에서 Promise 반환</h2>
<p>어떤 함수가 <code>Promise</code> 객체를 반환한다면 함수의 반환 타입으로 <code>Promise&lt;타입&gt;</code>을 지정해야 함.</p>
<pre><code class="language-ts">function fetchPost() {
  return new Promise&lt;Post&gt;((resolve, reject) =&gt; {
    setTimeout(() =&gt; {
      resolve({
        id: 1,
        title: &quot;게시글 제목&quot;,
        content: &quot;게시글 본문&quot;,
      });
    }, 3000);
  });
}</code></pre>
<p>또는 더 명확하게 반환 타입을 다음과 같이 직접 명시해도 됨.</p>
<pre><code class="language-ts">function fetchPost(): Promise&lt;Post&gt; {
  return new Promise((resolve, reject) =&gt; {
    setTimeout(() =&gt; {
      resolve({
        id: 1,
        title: &quot;게시글 제목&quot;,
        content: &quot;게시글 본문&quot;,
      });
    }, 3000);
  });
}</code></pre>
<hr>
<h1 id="요약">요약</h1>
<ul>
<li><code>Promise&lt;T&gt;</code>는 비동기 작업의 성공 결과를 <code>T</code>로 선언할 수 있도록 해주는 제네릭 클래스이다.</li>
<li><code>reject()</code> 결과값은 <code>unknown</code>으로 취급되므로 타입 확인이 필요하다.</li>
<li>함수 반환 타입으로 <code>Promise&lt;타입&gt;</code>을 사용하면 타입 안정성이 높아진다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-제네릭 클래스(5)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%81%B4%EB%9E%98%EC%8A%A45</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%81%B4%EB%9E%98%EC%8A%A45</guid>
            <pubDate>Tue, 15 Jul 2025 08:12:38 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-제네릭이-없는-클래스">✅ 제네릭이 없는 클래스</h2>
<pre><code class="language-ts">class NumberList {
  constructor(private list: number[]) {}

  push(data: number) {
    this.list.push(data);
  }

  pop() {
    return this.list.pop();
  }

  print() {
    console.log(this.list);
  }
}

const numberList = new NumberList([1, 2, 3]);</code></pre>
<h2 id="❌-비효율적인-클래스-중복-정의">❌ 비효율적인 클래스 중복 정의</h2>
<p>StringList도 필요하다면 클래스 정의를 중복하게 됨.</p>
<pre><code class="language-ts">class StringList {
  constructor(private list: string[]) {}

  push(data: string) {
    this.list.push(data);
  }

  pop() {
    return this.list.pop();
  }

  print() {
    console.log(this.list);
  }
}

const numberList = new NumberList([1, 2, 3]);
const stringList = new StringList([&quot;1&quot;, &quot;2&quot;, &quot;3&quot;]);</code></pre>
<p>이렇게 되면 코드 중복이 심하고 유지보수도 어려워짐.</p>
<hr>
<h2 id="✅-제네릭-클래스로-개선하기">✅ 제네릭 클래스로 개선하기</h2>
<p>다음과 같이 제네릭을 적용해 다양한 타입의 리스트를 처리할 수 있는 범용 클래스를 만들 수 있음.</p>
<pre><code class="language-ts">class List&lt;T&gt; {
  constructor(private list: T[]) {}

  push(data: T) {
    this.list.push(data);
  }

  pop() {
    return this.list.pop();
  }

  print() {
    console.log(this.list);
  }
}

const numberList = new List([1, 2, 3]);
const stringList = new List([&quot;1&quot;, &quot;2&quot;]);</code></pre>
<h3 id="🎯-타입-명시적으로-지정하기">🎯 타입 명시적으로 지정하기</h3>
<p>타입 추론이 가능하지만 명시적으로 타입을 지정할 수도 있음.</p>
<pre><code class="language-ts">const numberList = new List&lt;number&gt;([1, 2, 3]);
const stringList = new List&lt;string&gt;([&quot;1&quot;, &quot;2&quot;]);</code></pre>
<p>이처럼 제네릭 클래스는 코드 중복을 줄이고 다양한 타입을 유연하게 처리할 수 있어 효율적.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-제네릭 인터페이스, 제네릭 타입 별칭(4)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD4</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD4</guid>
            <pubDate>Tue, 15 Jul 2025 05:03:26 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li>제네릭은 <strong>인터페이스, 타입 별칭, 함수</strong> 등에 적용 가능</li>
<li>제네릭 인터페이스는 <strong>다양한 타입을 유연하게 표현</strong>할 수 있음</li>
<li><strong>인덱스 시그니처</strong>, <strong>유니온 타입</strong>, <strong>조건 분기</strong>, <strong>함수 매개변수 제한</strong> 등 실용도가 높음</li>
<li>타입 추론은 불가하므로 <strong>반드시 타입 인자를 명시해야 함</strong></li>
</ul>
<hr>
<h2 id="📌-기본-제네릭-인터페이스">📌 기본 제네릭 인터페이스</h2>
<pre><code class="language-ts">interface KeyPair&lt;K, V&gt; {
  key: K;
  value: V;
}

let keyPair: KeyPair&lt;string, number&gt; = {
  key: &quot;key&quot;,
  value: 0,
};

let keyPair2: KeyPair&lt;boolean, string[]&gt; = {
  key: true,
  value: [&quot;1&quot;],
};</code></pre>
<hr>
<h2 id="📌-인덱스-시그니처--제네릭">📌 인덱스 시그니처 + 제네릭</h2>
<pre><code class="language-ts">interface Map&lt;V&gt; {
  [key: string]: V;
}

let stringMap: Map&lt;string&gt; = {
  key: &quot;value&quot;,
};

let booleanMap: Map&lt;boolean&gt; = {
  key: true,
};</code></pre>
<hr>
<h2 id="📌-제네릭-타입-별칭">📌 제네릭 타입 별칭</h2>
<pre><code class="language-ts">type Map2&lt;V&gt; = {
  [key: string]: V;
};

let stringMap2: Map2&lt;string&gt; = {
  key: &quot;string&quot;,
};</code></pre>
<hr>
<h2 id="✅-제네릭-인터페이스-활용-예">✅ 제네릭 인터페이스 활용 예</h2>
<h3 id="타입-정의">타입 정의</h3>
<pre><code class="language-ts">interface Student {
  type: &quot;student&quot;;
  school: string;
}

interface Developer {
  type: &quot;developer&quot;;
  skill: string;
}</code></pre>
<hr>
<h3 id="제네릭-적용-전">제네릭 적용 전</h3>
<pre><code class="language-ts">interface User {
  name: string;
  profile: Student | Developer;
}

function goToSchool(user: User) {
  if (user.profile.type !== &quot;student&quot;) {
    console.log(&quot;잘 못 오셨습니다&quot;);
    return;
  }

  const school = user.profile.school;
  console.log(`${school}로 등교 완료`);
}</code></pre>
<hr>
<h3 id="제네릭-적용-후">제네릭 적용 후</h3>
<pre><code class="language-ts">interface User&lt;T&gt; {
  name: string;
  profile: T;
}

function goToSchool(user: User&lt;Student&gt;) {
  const school = user.profile.school;
  console.log(`${school}로 등교 완료`);
}

const developerUser: User&lt;Developer&gt; = {
  name: &quot;이정환&quot;,
  profile: {
    type: &quot;developer&quot;,
    skill: &quot;TypeScript&quot;,
  },
};

const studentUser: User&lt;Student&gt; = {
  name: &quot;홍길동&quot;,
  profile: {
    type: &quot;student&quot;,
    school: &quot;가톨릭대학교&quot;,
  },
};</code></pre>
<hr>
<h2 id="✅-마무리">✅ 마무리</h2>
<p>제네릭 인터페이스는 객체 설계 시<br><strong>다양한 타입을 유연하고 안전하게 다룰 수 있게 해주는 도구</strong>다.<br>함수, 타입 별칭, 조건 분기, 인덱스 구조 등과 조합하여 쓰면 매우 강력하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-map, forEach 메서드 타입 정의하기(3)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-map-forEach-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%83%80%EC%9E%85-%EC%A0%95%EC%9D%98%ED%95%98%EA%B8%B03</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-map-forEach-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%83%80%EC%9E%85-%EC%A0%95%EC%9D%98%ED%95%98%EA%B8%B03</guid>
            <pubDate>Tue, 15 Jul 2025 04:19:56 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li><code>map</code>과 <code>forEach</code> 메서드는 <strong>배열의 각 요소에 콜백을 적용</strong>하는 대표적인 고차함수</li>
<li><code>map</code>: 반환값을 기반으로 <strong>새로운 배열</strong> 생성</li>
<li><code>forEach</code>: 반환값 없이 <strong>순회 목적</strong>으로 사용</li>
<li>타입스크립트에서는 <strong>제네릭 타입</strong>을 사용해 다양한 타입에 대응 가능</li>
<li><code>map</code>의 경우 원본 배열과 <strong>다른 타입으로도 매핑 가능</strong>하므로 타입 변수를 2개 사용함</li>
</ul>
<hr>
<h2 id="📌-map-기본-구조">📌 map 기본 구조</h2>
<pre><code class="language-ts">const arr = [1, 2, 3];
const newArr = arr.map((it) =&gt; it * 2);
// 결과: [2, 4, 6]</code></pre>
<hr>
<h2 id="❌-일반-함수-버전">❌ 일반 함수 버전</h2>
<pre><code class="language-ts">function map(arr: unknown[], callback: (item: unknown) =&gt; unknown): unknown[] {
  // ...
}</code></pre>
<ul>
<li>타입 안정성이 없음</li>
<li>콜백 반환값이나 요소 타입 추론 불가</li>
</ul>
<hr>
<h2 id="✅-제네릭-map-함수---1차-버전">✅ 제네릭 map 함수 - 1차 버전</h2>
<pre><code class="language-ts">function map&lt;T&gt;(arr: T[], callback: (item: T) =&gt; T): T[] {
  let result = [];
  for (let i = 0; i &lt; arr.length; i++) {
    result.push(callback(arr[i]));
  }
  return result;
}</code></pre>
<pre><code class="language-ts">map([1, 2, 3], (it) =&gt; it * 2); // ✅ [2, 4, 6]
map([1, 2, 3], (it) =&gt; it.toString()); // ❌ 오류</code></pre>
<ul>
<li>T가 <code>number</code>로 고정되므로, <code>string</code> 반환 시 타입 충돌</li>
</ul>
<hr>
<h2 id="✅-제네릭-map-함수---2차-개선-버전">✅ 제네릭 map 함수 - 2차 개선 버전</h2>
<pre><code class="language-ts">function map&lt;T, U&gt;(arr: T[], callback: (item: T) =&gt; U): U[] {
  let result: U[] = [];
  for (let i = 0; i &lt; arr.length; i++) {
    result.push(callback(arr[i]));
  }
  return result;
}</code></pre>
<pre><code class="language-ts">map([1, 2, 3], (it) =&gt; it.toString()); // ✅ [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;]
map([&quot;a&quot;, &quot;b&quot;, &quot;c&quot;], (it) =&gt; it.length); // ✅ [1, 1, 1]</code></pre>
<ul>
<li>입력 타입 <code>T</code>, 반환 타입 <code>U</code> 분리</li>
<li>훨씬 유연한 타입 추론이 가능해짐</li>
</ul>
<hr>
<h2 id="📌-foreach-기본-구조">📌 forEach 기본 구조</h2>
<pre><code class="language-ts">const arr2 = [1, 2, 3];
arr2.forEach((it) =&gt; console.log(it));
// 출력: 1, 2, 3</code></pre>
<hr>
<h2 id="✅-제네릭-foreach-함수">✅ 제네릭 forEach 함수</h2>
<pre><code class="language-ts">function forEach&lt;T&gt;(arr: T[], callback: (item: T) =&gt; void) {
  for (let i = 0; i &lt; arr.length; i++) {
    callback(arr[i]);
  }
}</code></pre>
<ul>
<li>반환값이 없으므로 <code>void</code> 반환 타입 지정</li>
<li><code>map</code>보다 간단하고 안전하게 동작</li>
</ul>
<pre><code class="language-ts">forEach([&quot;a&quot;, &quot;b&quot;, &quot;c&quot;], (item) =&gt; {
  console.log(item.toUpperCase());
});</code></pre>
<hr>
<h2 id="✅-마무리-정리">✅ 마무리 정리</h2>
<table>
<thead>
<tr>
<th>함수명</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td>map</td>
<td>반환값 기반으로 <strong>새 배열 생성</strong>, <code>U[]</code> 반환</td>
</tr>
<tr>
<td>forEach</td>
<td>반환값 없음, <strong>순회 목적</strong>, <code>void</code> 반환</td>
</tr>
</tbody></table>
<p>제네릭을 활용하면 <strong>다양한 타입의 데이터</strong>에 대해<br><strong>안정적인 타입 추론과 오류 방지</strong>가 가능해진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-타입 변수 응용하기(2)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%83%80%EC%9E%85-%EB%B3%80%EC%88%98-%EC%9D%91%EC%9A%A9%ED%95%98%EA%B8%B02</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%83%80%EC%9E%85-%EB%B3%80%EC%88%98-%EC%9D%91%EC%9A%A9%ED%95%98%EA%B8%B02</guid>
            <pubDate>Mon, 14 Jul 2025 00:19:46 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li>제네릭은 <strong>타입의 재사용성과 정확성</strong>을 높이기 위해 사용됨</li>
<li>타입 변수는 여러 개(<code>T</code>, <code>U</code> 등) 동시에 사용할 수 있음</li>
<li>배열, 튜플 등 다양한 타입 구조에 활용 가능</li>
<li><code>extends</code>를 사용하면 타입 변수에 <strong>제한(제약 조건)</strong>을 걸 수 있음</li>
<li>활용 방법에 따라 <strong>타입 추론 정확도</strong>와 <strong>타입 안정성</strong>이 크게 향상됨</li>
</ul>
<hr>
<h2 id="📌-사례-1-두-개의-타입-변수-사용">📌 사례 1: 두 개의 타입 변수 사용</h2>
<pre><code class="language-ts">function swap&lt;T, U&gt;(a: T, b: U) {
  return [b, a];
}

const [a, b] = swap(&quot;1&quot;, 2);
// a: number, b: string</code></pre>
<ul>
<li><code>T = string</code>, <code>U = number</code>로 추론됨</li>
<li>여러 타입을 동시에 사용할 수 있음</li>
</ul>
<hr>
<h2 id="📌-사례-2-제네릭-배열">📌 사례 2: 제네릭 배열</h2>
<pre><code class="language-ts">function returnFirstValue&lt;T&gt;(data: T[]) {
  return data[0];
}

let num = returnFirstValue([0, 1, 2]); 
// number

let str = returnFirstValue([1, &quot;hello&quot;, &quot;mynameis&quot;]); 
// number | string</code></pre>
<ul>
<li><code>T[]</code>를 매개변수 타입으로 설정하면 <code>T</code>는 요소의 타입으로 추론됨</li>
<li>혼합된 타입 배열의 경우 <code>T</code>는 <code>number | string</code></li>
</ul>
<hr>
<h2 id="📌-사례-3-튜플-타입으로-첫-번째-요소-추론">📌 사례 3: 튜플 타입으로 첫 번째 요소 추론</h2>
<pre><code class="language-ts">function returnFirstValue&lt;T&gt;(data: [T, ...unknown[]]) {
  return data[0];
}

let str = returnFirstValue([1, &quot;hello&quot;, &quot;mynameis&quot;]);
// number</code></pre>
<ul>
<li>첫 번째 요소의 타입만 <code>T</code>로 고정</li>
<li>나머지 요소는 어떤 타입이든 상관없음 (<code>...unknown[]</code>)</li>
</ul>
<hr>
<h2 id="📌-사례-4-타입-변수-제한-extends">📌 사례 4: 타입 변수 제한 (<code>extends</code>)</h2>
<pre><code class="language-ts">function getLength&lt;T extends { length: number }&gt;(data: T) {
  return data.length;
}

getLength(&quot;123&quot;);            // ✅ OK
getLength([1, 2, 3]);        // ✅ OK
getLength({ length: 1 });    // ✅ OK
getLength(undefined);        // ❌ 오류
getLength(null);             // ❌ 오류</code></pre>
<ul>
<li><code>T extends { length: number }</code>는 T가 최소한 <code>length</code> 프로퍼티를 가지고 있어야 함</li>
<li>타입 안정성을 위해 필요한 제약 조건</li>
</ul>
<hr>
<h2 id="✅-마무리">✅ 마무리</h2>
<p>제네릭은 단순히 타입을 일반화하는 것이 아니라<br><strong>상황에 맞는 타입 정확성과 제한을 추가하는 도구</strong>이다.<br>적절히 활용하면 코드의 안정성과 유연성이 크게 향상된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-제네릭 소개(1)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%86%8C%EA%B0%9C1</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%86%8C%EA%B0%9C1</guid>
            <pubDate>Sun, 13 Jul 2025 23:00:47 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<p><strong>C++의 템플릿 함수와 동일. <T>로 입력된 타입에 따라 자동 추론</strong></p>
<ul>
<li>제네릭(Generic)은 함수, 클래스, 타입 등을 <strong>다양한 타입과 함께 동작하도록</strong> 만들어주는 기능</li>
<li><code>any</code>나 <code>unknown</code>으로는 타입 안정성을 완전히 확보하기 어려움</li>
<li>제네릭을 사용하면 <strong>입력된 타입에 따라 반환 타입을 자동으로 지정</strong>할 수 있음</li>
<li>호출 시 직접 타입을 명시할 수도 있고, 대부분은 자동 추론됨</li>
<li>코드의 재사용성과 타입 안정성을 동시에 확보할 수 있음</li>
</ul>
<hr>
<h2 id="📌-제네릭이-필요한-상황">📌 제네릭이 필요한 상황</h2>
<pre><code class="language-ts">function func(value: any) {
  return value;
}

let num = func(10);       // any 타입
let str = func(&quot;string&quot;); // any 타입

num.toUpperCase(); // 런타임 오류 발생 가능 (컴파일러가 감지 못함)</code></pre>
<hr>
<h2 id="❓-unknown을-사용한-경우">❓ unknown을 사용한 경우</h2>
<pre><code class="language-ts">function func(value: unknown) {
  return value;
}

let num = func(10);
let str = func(&quot;string&quot;);

num.toFixed(); // ❌ 오류</code></pre>
<p>→ <code>unknown</code>은 안전하지만 <strong>사용 전 타입 좁히기 필요</strong>. 귀찮고 불편하다.</p>
<hr>
<h2 id="💡-우리가-원하는-것">💡 우리가 원하는 것</h2>
<ul>
<li>전달한 인수의 타입이 그대로 반환 타입으로 반영되기를 원함</li>
</ul>
<hr>
<h2 id="✅-제네릭-함수로-해결">✅ 제네릭 함수로 해결</h2>
<pre><code class="language-ts">function func&lt;T&gt;(value: T): T {
  return value;
}

let num = func(10);         // number 타입
let str = func(&quot;string&quot;);   // string 타입</code></pre>
<ul>
<li><code>&lt;T&gt;</code>: 타입 변수를 선언</li>
<li><code>T</code>는 함수 호출 시 결정됨 (여기선 <code>number</code>, <code>string</code>)</li>
</ul>
<hr>
<h2 id="✍-타입을-명시적으로-지정하기">✍ 타입을 명시적으로 지정하기</h2>
<pre><code class="language-ts">function func&lt;T&gt;(value: T): T {
  return value;
}

let arr = func&lt;[number, number, number]&gt;([1, 2, 3]);</code></pre>
<ul>
<li><code>T</code>에 튜플 타입을 직접 지정함</li>
<li>타입스크립트는 일반적으로 <code>number[]</code>로 추론하므로, <strong>정밀한 타입 추론이 필요할 땐 직접 명시</strong></li>
</ul>
<hr>
<h2 id="📌-요약">📌 요약</h2>
<ul>
<li><code>any</code>는 너무 느슨하고, <code>unknown</code>은 너무 엄격함</li>
<li>제네릭은 타입을 <strong>입력값에 맞춰 자동으로 설정</strong>해줌</li>
<li><code>&lt;T&gt;</code>와 같은 타입 변수 사용</li>
<li>함수, 클래스, 인터페이스 등 여러 곳에서 활용 가능</li>
<li>명시적으로 타입을 넘길 수도 있고, 자동 추론도 대부분 잘 작동함</li>
</ul>
<hr>
<p>제네릭은 타입스크립트의 가장 강력한 기능 중 하나로,<br><strong>안정성과 유연성</strong>을 동시에 만족시킬 수 있는 패턴이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션6. 클래스-인터페이스와 클래스(4)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%986.-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%99%80-%ED%81%B4%EB%9E%98%EC%8A%A44</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%986.-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%99%80-%ED%81%B4%EB%9E%98%EC%8A%A44</guid>
            <pubDate>Sun, 13 Jul 2025 22:52:00 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<p><strong>c++, java랑 동일.</strong></p>
<ul>
<li>인터페이스는 클래스가 따라야 할 구조를 명시함</li>
<li><code>implements</code>를 사용해 클래스가 특정 인터페이스를 구현하게 할 수 있음</li>
<li>인터페이스에 명시된 필드/메서드는 클래스에서 모두 구현해야 함</li>
<li>접근 제어자 <code>public</code>인 필드만 인터페이스 조건을 만족함</li>
</ul>
<hr>
<h2 id="✅-인터페이스와-클래스">✅ 인터페이스와 클래스</h2>
<p>타입스크립트의 인터페이스는 <strong>클래스의 설계도</strong> 역할을 할 수 있다.<br>클래스가 어떤 필드와 메서드를 가져야 하는지 명확히 정의할 수 있다.</p>
<hr>
<h2 id="📌-기본-구조">📌 기본 구조</h2>
<pre><code class="language-ts">interface CharacterInterface {
  name: string;
  moveSpeed: number;
  move(): void;
}</code></pre>
<p><code>CharacterInterface</code>는 다음 3가지를 요구한다:</p>
<ul>
<li><code>name</code>: 문자열</li>
<li><code>moveSpeed</code>: 숫자</li>
<li><code>move()</code>: 반환값이 없는 함수</li>
</ul>
<hr>
<h2 id="✍-클래스에서-인터페이스-구현">✍ 클래스에서 인터페이스 구현</h2>
<p>인터페이스를 클래스에 적용하려면 <code>implements</code> 키워드를 사용한다.</p>
<pre><code class="language-ts">class Character implements CharacterInterface {
  constructor(
    public name: string,
    public moveSpeed: number,
    private extra: string
  ) {}

  move(): void {
    console.log(`${this.moveSpeed} 속도로 이동!`);
  }
}</code></pre>
<ul>
<li><code>implements</code>를 사용하면, 클래스는 해당 인터페이스를 <strong>완전히 구현해야</strong> 한다.</li>
<li><code>public</code>으로 선언된 필드는 인터페이스 요구사항을 만족시킨다.</li>
<li><code>extra</code> 필드는 <code>private</code>이기 때문에 인터페이스에 없어도 무관하다.</li>
</ul>
<hr>
<p>인터페이스 기반 설계를 활용하면 코드의 <strong>일관성과 가독성</strong>,  
그리고 <strong>유지보수성</strong>이 크게 향상된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션6. 클래스-접근 제어자(3)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%986.-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%A0%91%EA%B7%BC-%EC%A0%9C%EC%96%B4%EC%9E%903</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%986.-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%A0%91%EA%B7%BC-%EC%A0%9C%EC%96%B4%EC%9E%903</guid>
            <pubDate>Sun, 13 Jul 2025 22:48:15 GMT</pubDate>
            <description><![CDATA[<h1 id="✅선요약">✅선요약</h1>
<p><strong>c++ 접근 제어자와 거의 동일
다른 점은 멤버 변수 앞에 private나 protected를 각각 붙혀서 사용.
접근 제어자는 생성자 매개변수에 직접 설정 가능하다.<br>이 경우 필드 선언과 초기화 코드를 생략할 수 있다.</strong></p>
<ul>
<li>접근 제어자는 <code>public</code>, <code>private</code>, <code>protected</code> 세 가지가 있음</li>
<li><code>public</code>: 어디서든 접근 가능 (기본값)</li>
<li><code>private</code>: 클래스 내부에서만 접근 가능</li>
<li><code>protected</code>: 클래스 내부 + 파생 클래스에서만 접근 가능</li>
<li>생성자 매개변수에 접근 제어자를 붙이면 필드 선언 및 초기화가 자동으로 이루어짐</li>
<li>접근 제어자 사용 시 코드 간결성과 정보 은닉성이 향상됨</li>
</ul>
<hr>
<h1 id="타입스크립트-접근-제어자">타입스크립트 접근 제어자</h1>
<h2 id="✅-접근-제어자란">✅ 접근 제어자란?</h2>
<p>타입스크립트에서 제공하는 기능으로,<br>클래스의 필드나 메서드에 대해 <strong>외부에서의 접근 범위</strong>를 설정할 수 있다.</p>
<p>사용 가능한 접근 제어자는 다음 세 가지이다:</p>
<ul>
<li><code>public</code>: 어디서든 접근 가능 (기본값)</li>
<li><code>private</code>: 클래스 내부에서만 접근 가능</li>
<li><code>protected</code>: 클래스 내부 또는 파생 클래스에서만 접근 가능</li>
</ul>
<hr>
<h2 id="📌-public-기본-접근-제어자">📌 public (기본 접근 제어자)</h2>
<pre><code class="language-ts">class Employee {
  name: string;
  age: number;
  position: string;

  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  work() {
    console.log(&quot;일함&quot;);
  }
}

const employee = new Employee(&quot;이정환&quot;, 27, &quot;developer&quot;);

employee.name = &quot;홍길동&quot;;      // ✅ 가능
employee.age = 30;            // ✅ 가능
employee.position = &quot;디자이너&quot;; // ✅ 가능</code></pre>
<p>명시적으로 <code>public</code>을 붙여도 결과는 동일하다.</p>
<hr>
<h2 id="🔐-private">🔐 private</h2>
<pre><code class="language-ts">class Employee {
  private name: string;
  public age: number;
  public position: string;

  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  work() {
    console.log(`${this.name}이 일함`);
  }
}

const employee = new Employee(&quot;이정환&quot;, 27, &quot;developer&quot;);

employee.name = &quot;홍길동&quot;; // ❌ 오류: private 접근 불가
employee.age = 30;        // ✅</code></pre>
<p><code>private</code> 필드는 클래스 외부에서 접근이 불가하다.<br>단, 클래스 내부 메서드에서는 사용 가능하다.</p>
<hr>
<h2 id="🛡-protected">🛡 protected</h2>
<pre><code class="language-ts">class Employee {
  private name: string;
  protected age: number;
  public position: string;

  constructor(name: string, age: number, position: string) {
    this.name = name;
    this.age = age;
    this.position = position;
  }

  work() {
    console.log(`${this.name}이 일함`);
  }
}

class ExecutiveOfficer extends Employee {
  func() {
    this.age;  // ✅ protected 접근 가능
    this.name; // ❌ private 접근 불가
  }
}

const employee = new Employee(&quot;이정환&quot;, 27, &quot;developer&quot;);

employee.age = 30;   // ❌ 외부 접근 불가
employee.position = &quot;디자이너&quot;; // ✅</code></pre>
<hr>
<h2 id="✍-생성자에서-필드-생략하기">✍ 생성자에서 필드 생략하기</h2>
<p>접근 제어자는 <strong>생성자 매개변수에 직접 설정 가능</strong>하다.<br>이 경우 필드 선언과 초기화 코드를 생략할 수 있다.</p>
<pre><code class="language-ts">class Employee {
  constructor(
    private name: string,
    protected age: number,
    public position: string
  ) {}

  work() {
    console.log(`${this.name} 일함`);
  }
}</code></pre>
<p>위 코드에서 <code>this.name = name</code> 같은 코드가 없어도<br>자동으로 필드 선언 + 초기화가 함께 이루어진다.</p>
<hr>
]]></description>
        </item>
    </channel>
</rss>