diff --git a/Aug/article/Leveraging-TypeScript-branded-types-for-stronger-type-checks.md b/Aug/article/Leveraging-TypeScript-branded-types-for-stronger-type-checks.md
new file mode 100644
index 0000000..150f714
--- /dev/null
+++ b/Aug/article/Leveraging-TypeScript-branded-types-for-stronger-type-checks.md
@@ -0,0 +1,284 @@
+## ๐ [Leveraging TypeScript branded types for stronger type checks](https://blog.logrocket.com/leveraging-typescript-branded-types-stronger-type-checks/)
+
+### ๐๏ธ ๋ฒ์ญ ๋ ์ง: 2024.08.04
+
+### ๐ง ๋ฒ์ญํ ํฌ๋ฃจ: ๋ ์(๊น๋ค์)
+
+---
+
+## TypeScript ๋ธ๋๋ ํ์
์ ํ์ฉํ์ฌ ๋ ๊ฐ๋ ฅํ ํ์
๊ฒ์ฌํ๊ธฐ
+
+TypeScript์ ๋ธ๋๋ ํ์
์ ๋ ๋ช
ํํ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๋ ํ์
์์ ํ ์๋ฃจ์
์ ์ ๊ณตํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ๋ ๋งค์ฐ ๊ฐ๋จํ๋ฉฐ, ์ฝ๋ ์ ์ง ๋ณด์๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ํ ์ ์๊ฒ ๋์์ค๋๋ค.
+
+
+
+![](https://blog.logrocket.com/wp-content/uploads/2024/07/Leveraging-TypeScript-branded-types-stronger-type-checks.png)
+
+
+
+์ด ๊ธฐ์ฌ์์๋ ๊ฐ๋จํ ์์ ๋ถํฐ ์์ํ์ฌ ๋ช ๊ฐ์ง ๊ณ ๊ธ ์ฌ์ฉ ์ฌ๋ก์ ์ด๋ฅด๊ธฐ๊น์ง, TypeScript ์ฝ๋์์ ๋ธ๋๋ ํ์
์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ณด๊ฒ ์ต๋๋ค. ์์ํด๋ด
์๋ค.
+
+## TypeScript์ ๋ธ๋๋ ํ์
์ด๋ ๋ฌด์์ธ๊ฐ์?
+
+TypeScript์ ๋ธ๋๋ ํ์
์ ์ฝ๋ ๊ฐ๋
์ฑ, ๋งฅ๋ฝ, ํ์
์์ ์ฑ์ ํฅ์์ํค๊ธฐ ์ํ ๋งค์ฐ ๊ฐ๋ ฅํ๊ณ ํจ์จ์ ์ธ ๊ธฐ๋ฅ์
๋๋ค. ์ด ํ์
์ ๊ธฐ์กด ํ์
์ ์ถ๊ฐ ์ ์๋ฅผ ์ ๊ณตํ์ฌ ๊ตฌ์กฐ์ ํ์ผ ์ด๋ฆ์ด ์ ์ฌํ ์ํฐํฐ๋ฅผ ๋น๊ตํ ์ ์๊ฒ ํฉ๋๋ค.
+
+์๋ฅผ ๋ค์ด, ๋ฌธ์์ด๋ก ์ฌ์ฉ์ ์ด๋ฉ์ผ์ ์ ์ฅํ๋ ๋์ , ์ด๋ฉ์ผ ์ฃผ์์ ๋ํ ๋ธ๋๋ TypeScript ํ์
์ ๋ง๋ค์ด ์ผ๋ฐ ๋ฌธ์์ด๊ณผ ๊ตฌ๋ถํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ํฐํฐ๋ฅผ ๋ ์ฒด๊ณ์ ์ผ๋ก ๊ฒ์ฆํ ์ ์๊ณ ์ฝ๋๋ ๋ช
ํํด์ง๋๋ค.
+
+๋ธ๋๋ ํ์
์์ด ์ฐ๋ฆฌ๋ ์ผ๋ฐ์ ์ผ๋ก ๋๋ถ๋ถ์ ๊ฒฝ์ฐ์ฒ๋ผ ๊ฐ๋ค์ ์ ๋ค๋ฆญ ํ์
๋ณ์์ ์ ์ฅํฉ๋๋ค. ๋ธ๋๋ ํ์
์ ์ฌ์ฉํ๋ฉด ํด๋น ๋ณ์๋ฅผ ๊ฐ์กฐํ๊ณ ์ฝ๋ ์ ๋ฐ์์ ๊ทธ ์ ํจ์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
+
+## ๊ฐ๋จํ TypeScript ๋ธ๋๋ ํ์
์์
+
+์ด๋ฉ์ผ ์ฃผ์๋ฅผ ์ํ ๋ธ๋๋ ํ์
์ ๋ง๋ค์ด๋ด
์๋ค. type์ ๋ธ๋๋ ์ด๋ฆ์ ๋ถ์ด๋ ๊ฒ์ผ๋ก ๋ธ๋๋ ํ์
์ ์์ฑํ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ, ์ด๋ฉ์ผ ์ฃผ์์ ๋ํ ๋ธ๋๋ ํ์
์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
+
+```ts
+type EmailAddress = string & { __brand: 'EmailAddress' };
+```
+
+์ฌ๊ธฐ์, ์ฐ๋ฆฌ๋ \_\_brand ์ด๋ฆ 'EmailAddress'๋ฅผ ๋ถ์ฌ์ ๋ธ๋๋ ํ์
EmailAddress๋ฅผ ๋ง๋ค์์ต๋๋ค.
+
+๋ธ๋๋ ํ์
์ ๋ง๋ค ๋ ์ ๋ค๋ฆญ ๋ฌธ๋ฒ์ ํ์์๋ค๋ ์ฌ์ค์ ๋ช
์ฌํ์ธ์. ๋ธ๋๋ ํ์
์ ์ ๋ค๋ฆญ(๋ฌธ์์ด, ์ซ์ ๋ฑ)์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. \_\_brand ๋ฌธ๋ฒ๋ ์์ฝ์ด๊ฐ ์๋๋ฏ๋ก \_\_brand ์ธ์ ๋ค๋ฅธ ๋ณ์ ์ด๋ฆ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+
+์ด์ EmailAddress ํ์
์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ๋ฌธ์์ด์ ์ ๋ฌํด ๋ด
์๋ค:
+
+```ts
+const email: EmailAddress = 'asd'; // error
+```
+
+๋ณด์๋ ๋ฐ์ ๊ฐ์ด ํ์
์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
+
+```shell
+Type 'string' is not assignable to type 'EmailAddress.' Type 'string' is not assignable to type '{ __brand: "EmailAddress"; }.'
+```
+
+์ด๋ฅผ ๊ณ ์น๊ธฐ ์ํด์ ์ด๋ฉ์ผ ์ฃผ์์ ๋ํ ๊ธฐ๋ณธ์ ์ธ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์์ฑํด๋ด
์๋ค.
+
+```ts
+const isEmailAddress = (email: string): email is EmailAddress => {
+ return email.endsWith('@gmail.com');
+};
+```
+
+์ฌ๊ธฐ์ boolean ๊ฐ์ ๋ฐํํ๋ ๋์ , `email is EmailAddress`๋ฅผ ๋ฐํํ๊ณ ์์ต๋๋ค. ์ด๋ ํจ์๊ฐ `true`๋ฅผ ๋ฐํํ๋ฉด email์ด `EmailAddress` [ํ์
์ผ๋ก ์บ์คํ
](https://blog.logrocket.com/how-to-perform-type-casting-typescript/)๋๋ค๋ ์๋ฏธ์
๋๋ค. ์ด๋ฅผ ํตํด ๋ฌธ์์ด์ ๋ํด ์ด๋ค ์์
์ ์ํํ๊ธฐ ์ ์ ์ ํจ์ฑ์ ๊ฒ์ฆํ ์ ์์ต๋๋ค.
+
+```ts
+const sendVerificationEmail = (email: EmailAddress) => {
+ //...
+};
+const signUp = (email: string, password: string) => {
+ //...
+ if (isEmailAddress(email)) {
+ sendVerificationEmail(email); // pass
+ }
+ sendVerificationEmail(email); // error
+};
+```
+
+๋ณด์๋ ๋ฐ์ ๊ฐ์ด, ์ค๋ฅ๋ if ์กฐ๊ฑด๋ฌธ ์์์ ๋ณด์ด์ง ์์ง๋ง, ํด๋น ์กฐ๊ฑด๋ฌธ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ฉด ๋ฐ์ํฉ๋๋ค.
+
+`assert`๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ ๊ฒ์ฆํ ์๋ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ฒ์ฆ์ด ํต๊ณผ๋์ง ์์ ๊ฒฝ์ฐ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๊ณ ์ ํ ๋ ์ ์ฉํ ์ ์์ต๋๋ค.
+
+```ts
+function assertEmailAddress(email: string): asserts email is EmailAddress {
+ if (!email.endsWith('@gmail.com')) {
+ throw new Error('Not an email addres');
+ }
+}
+
+const sendVerificationEmail = (email: EmailAddress) => {
+ //...
+};
+
+const signUp = (email: string, password: string) => {
+ //...
+ assertEmailAddress(email);
+ sendVerificationEmail(email); // ok
+};
+```
+
+์ฌ๊ธฐ์ ๋ณด์๋ค์ํผ, ๋ฐํ ํ์
์ผ๋ก `asserts email is EmailAddress`๋ฅผ ๋ช
์ํ๊ณ ์์ต๋๋ค. ์ด๋ ๊ฒ์ฆ์ด ํต๊ณผํ๋ฉด ์ด๋ฉ์ผ ์ฃผ์๊ฐ ๋ธ๋๋ ํ์
`EmailAddress`์์ ๋ณด์ฅํฉ๋๋ค.
+
+## TypeScript์์ ๋ธ๋๋ ํ์
์ ๊ณ ๊ธ ์ฌ์ฉ ์ฌ๋ก
+
+์ ์์๋ ๋ธ๋๋ ํ์
์ ๊ฐ๋จํ ์์ฐ์
๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฅผ ๋ ๊ณ ๊ธ ์ฌ๋ก์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์์๋ฅผ ํ๋ ๋ณด๊ฒ ์ต๋๋ค.
+
+๋จผ์ , ๋ค๋ฅธ ํ์
์ ๋ถ์ผ ์ ์๋ ๊ณตํต Branded ํ์
์ ์ ์ธํด ๋ด
์๋ค:
+
+```ts
+declare const __brand: unique symbol;
+type Brand = { [__brand]: B };
+export type Branded = T & Brand;
+```
+
+์ฌ๊ธฐ์, ์ฌ๋ณผ์ ์ฌ์ฉํด ๊ฐ ํ์
์ ๊ตฌ๋ถํ๋ ๊ณ ์ ํ ๋ธ๋๋๋ฅผ ๋ง๋ญ๋๋ค. ์ฌ๋ณผ์ ๋ค๋ฅธ ์ด๋ค ์ฌ๋ณผ๊ณผ๋ ๊ตฌ๋ณ๋๋ ์ ์ผํ ์ฌ๋ณผ์์ ๋ณด์ฅํฉ๋๋ค. ์ด๋ ์๋ก์ด ์ฌ๋ณผ์ ์์ฑํ ๋๋ง๋ค ๋ค๋ฅธ ์ฌ๋ณผ๊ณผ ๊ตฌ๋ณ๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋ค์์ ์ด๋ฅผ ์ค๋ช
ํ๋ ์์ ์
๋๋ค:
+
+```ts
+// ๋ธ๋๋๋ก ์ฌ์ฉํ ๊ณ ์ ์ฌ๋ณผ ์ ์
+const metersSymbol: unique symbol = Symbol('meters');
+const kilometersSymbol: unique symbol = Symbol('kilometers');
+
+// ๋ธ๋๋ ํ์
์ ์
+type Meters = number & { [metersSymbol]: void };
+type Kilometers = number & { [kilometersSymbol]: void };
+
+// ๋ธ๋๋ ๊ฐ์ ์์ฑํ๋ ๋์ฐ๋ฏธ ํจ์
+function meters(value: number): Meters {
+ return value as Meters;
+}
+
+function kilometers(value: number): Kilometers {
+ return value as Kilometers;
+}
+
+// ๋ธ๋๋ ํ์
์ ๊ฐ์ง ๋ณ์๋ค
+const distanceInMeters: Meters = meters(100);
+const distanceInKilometers: Kilometers = kilometers(1);
+
+// ์๋ ํ ๋น์ ํ์
์ค๋ฅ๋ฅผ ๋ฐ์์ํด
+const wrongDistance: Meters = distanceInKilometers;
+const anotherWrongDistance: Kilometers = distanceInMeters;
+
+// ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ๋ฒ
+const anotherDistanceInMeters: Meters = meters(200);
+const anotherDistanceInKilometers: Kilometers = kilometers(2);
+
+console.log(distanceInMeters, distanceInKilometers);
+```
+
+๊ณตํต Branded ํ์
์ธํฐํ์ด์ค๋ฅผ ๊ฐ์ง๋ฉด TypeScript์์ ์ฌ๋ฌ ๋ธ๋๋ ํ์
์ ๋์์ ์์ฑํ ์ ์์ด, ์ฝ๋ ๊ตฌํ์ ์ค์ด๊ณ ์ฝ๋๋ฅผ ํจ์ฌ ๊น๋ํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ์ด์ ์์ ์ด๋ฉ์ผ ๊ฒ์ฆ ์์ ๋ฅผ ํ์ฅํ์ฌ, ์ด ๊ณตํต Branded ํ์
์ ์ฌ์ฉํด EmailAddress ๋ธ๋๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ ์ ์์ต๋๋ค:
+
+```ts
+type EmailAddress = Branded;
+
+const isEmailAddress = (email: string): email is EmailAddress => {
+ return email.endsWith('@gmail.com');
+};
+
+const sendEmail = (email: EmailAddress) => {
+ // ...
+};
+
+const signUp = (email: string, password: string) => {
+ if (isEmailAddress(email)) {
+ // ์ธ์ฆ ๋ฉ์ผ ์ ์ก
+ sendEmail(email);
+ }
+};
+```
+
+์ด์ ์ด Branded ํ์
์ ์ฌ์ฉํ์ฌ ์๋ก์ด ๋ธ๋๋ TypeScript ํ์
์ ๋ง๋ค ์ ์์ต๋๋ค. Branded ํ์
์ ์ฌ์ฉํ๋ ๋ ๋ค๋ฅธ ์๋ฅผ ์ดํด๋ด
์๋ค. ์ฌ์ฉ์๊ฐ ๊ฒ์๋ฌผ์ ์ข์ํ ์ ์๋๋ก ํ๋ ํจ์๋ฅผ ์์ฑํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. userId์ postId ๋ชจ๋์ Branded ํ์
์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
+
+```ts
+type UserId = Branded;
+type PostId = Branded;
+
+type User = {
+ userId: UserId;
+ username: string;
+ email: string;
+};
+
+type Post = {
+ postId: PostId;
+ title: string;
+ description: string;
+ likes: Like[];
+};
+
+type Like = {
+ userId: UserId;
+ postId: PostId;
+};
+
+const likePost = async (userId: UserId, postId: PostId) => {
+ const response = await fetch(`/posts/${postId}/like/${userId}`, {
+ method: 'post',
+ });
+ return await response.json();
+};
+
+// ๊ฐ์์ ๊ฐ์ฒด
+const user: User = {
+ userId: '1' as UserId,
+ email: 'a@email.com',
+ username: 'User1',
+};
+const post: Post = {
+ postId: '2' as PostId,
+ title: 'Sample Title',
+ description: 'Sample post description',
+ likes: [],
+};
+
+likePost(user.userId, post.postId); // ok
+likePost(post.postId, user.userId); // error
+```
+
+## TypeScript 5.5-beta์์ ๋ธ๋๋ ํ์
์ผ๋ก ์์
ํ๊ธฐ
+
+์๋ก์ด TypeScript 5.5-beta ๋ฆด๋ฆฌ์ค์์๋ TypeScript์ ์ ์ด ํ๋ฆ ๋ถ์์ด ์ฝ๋๊ฐ ์งํ๋จ์ ๋ฐ๋ผ ๋ณ์์ ํ์
์ด ์ด๋ป๊ฒ ๋ณํ๋์ง ์ถ์ ํ ์ ์๊ฒ ๋์์ต๋๋ค.
+
+์ด๋ ๋ณ์์ ํ์
์ด ์ฝ๋ ๋ก์ง์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ ์ ์์ผ๋ฉฐ, TypeScript๊ฐ ์ฝ๋ ๋ก์ง์ ๊ฐ ์์ ์ฒด์ธ์์ ๋ณ์ ํ์
์ ์ถ์ ํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋ณ์๊ฐ ๊ฐ์ง ์ ์๋ ๋ ๊ฐ์ง ๊ฐ๋ฅํ ํ์
์ด ์๋ ๊ฒฝ์ฐ, ํ์ํ ์กฐ๊ฑด์ ์ ์ฉํ์ฌ ๋ณ์์ ํ์
์ ๋ถ๋ฆฌํ ์ ์์ต๋๋ค.
+
+์๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด์ ์ดํดํด๋ด
์๋ค:
+
+```tsx
+interface ItemProps {
+ // ...
+}
+
+declare const items: Map;
+
+function getItem(id: string) {
+ const item = items.get(id); // item์ ItemProps | undefined ํ์
์ผ๋ก ์ ์ธ๋จ
+ if (item) {
+ // if ๋ฌธ ์์์ item์ ItemProps ํ์
์ ๊ฐ์ง
+ } else {
+ // ์ฌ๊ธฐ์ item์ undefined ํ์
์ ๊ฐ์ง
+ }
+}
+
+function getAllItemsByIds(ids: string[]): ItemProps[] {
+ return ids.map((id) => items.get(id)).filter((item) => item !== undefined); // ์ด์ ์๋ ์ด๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: Type '(ItemProps | undefined)[]' is not assignable to type 'ItemProps[]'. Type 'ItemProps | undefined' is not assignable to type 'ItemProps'. Type 'undefined' is not assignable to type 'ItemProps'
+}
+```
+
+๋ค์ ์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด ์์ ์์๋ ์ด๋ฉ์ผ ์ฃผ์ ๋ชฉ๋ก์ ๊ฐ์ ธ์์ ๊ฒ์ฆ๋ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํฉ๋๋ค. ์ด์ ์์ ๋ฅผ ์ฌ์ฉํ์ฌ ๋ธ๋๋ EmailAddress ํ์
์ ์์ฑํ๊ณ ๊ฒ์ฆ๋ ์ด๋ฉ์ผ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ ์ ์์ต๋๋ค:
+
+```ts
+type EmailAddress = Branded;
+const isEmailAddress = (email: string): email is EmailAddress => {
+ return email.endsWith('@gmail.com');
+};
+
+const storeToDb = async (emails: EmailAddress[]) => {
+ const response = await fetch('/store-to-db', {
+ body: JSON.stringify({
+ emails,
+ }),
+ method: 'post',
+ });
+ return await response.json();
+};
+
+const emails = ['a@gmail.com', 'b@gmail.com', '...'];
+const validatedEmails = emails.filter((email) => isEmailAddress(email));
+storeToDb(validatedEmails); // error
+```
+
+์ฌ๊ธฐ์ ๊ฒ์ฆ๋ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ validatedEmails ๋ฐฐ์ด์ ๋์ดํ๊ณ ์์ง๋ง, storeToDb ํจ์์ ์ ๋ฌํ ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ์ด ์ค๋ฅ๋ ํนํ v5.5-beta ์ด์ ์ TypeScript ๋ฒ์ ์ ์ฌ์ฉํ ๋ ๋ํ๋ฉ๋๋ค.
+
+๋ฎ์ ๋ฒ์ ์ TypeScript์์๋ validatedEmails ๋ฐฐ์ด์ ํ์
์ด ์๋ ๋ณ์์ธ emails ๋ฐฐ์ด์์ ํ์๋ฉ๋๋ค. ๊ทธ๋์ validatedEmails ๋ฐฐ์ด์ ํ์
์ด string[]๋ก ๋ํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ฌธ์ ๋ ํ์ฌ TypeScript ๋ฒ ํ ๋ฒ์ (ํ์ฌ ๊ธฐ์ค์ผ๋ก 5.5-beta)์์ ํด๊ฒฐ๋์์ต๋๋ค.
+
+ํ์ฌ ๋ฒ ํ ๋ฒ์ ์์๋ ๊ฒ์ฆ๋ ์ด๋ฉ์ผ์ ํํฐ๋งํ ํ์ validatedEmails๊ฐ ์๋์ผ๋ก EmailAddress[]๋ก ํ์
์บ์คํ
๋ฉ๋๋ค. ๋ฐ๋ผ์ TypeScript 5.5-beta ๋ฒ์ ์์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค. ํ๋ก์ ํธ์ TypeScript ๋ฒ ํ ๋ฒ์ ์ ์ค์นํ๋ ค๋ฉด ํฐ๋ฏธ๋์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ์ญ์์ค:
+
+```shell
+npm install -D typescript@beta
+```
+
+
+
+## ๊ฒฐ๋ก
+
+๋ธ๋๋ ํ์
์ TypeScript์์ ๋งค์ฐ ์ ์ฉํ ๊ธฐ๋ฅ์
๋๋ค. ์ด๋ค์ ๋ฐํ์ ํ์
์์ ์ฑ์ ์ ๊ณตํ์ฌ ์ฝ๋ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๊ณ ๊ฐ๋
์ฑ์ ํฅ์์ํต๋๋ค. ๋ํ ๋๋ฉ์ธ ์์ค์์ ์ค๋ฅ๋ฅผ ๋ฐ์์์ผ ์ฝ๋์ ๋ฒ๊ทธ๋ฅผ ์ค์ด๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
+
+๋ธ๋๋ ํ์
์ ์ฝ๊ฒ ๊ฒ์ฆํ๊ณ , ๊ฒ์ฆ๋ ๊ฐ์ฒด๋ฅผ ํ๋ก์ ํธ ์ ๋ฐ์ ๊ฑธ์ณ ์์ ํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ต์ TypeScript ๋ฒ ํ ๋ฒ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์ฝ๋ฉ ๊ฒฝํ์ ๋์ฑ ์ํํ๊ฒ ํ์ฉํ ์ ์์ต๋๋ค.