๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

TypeScript ๊ธฐ์ดˆ๐Ÿค

ยท ์•ฝ 9๋ถ„
์‹ฌ์™„

TypeScript์˜ ๊ธฐ์ดˆ์ ์ธ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

Typescript ์†Œ๊ฐœโ€‹

Typescript๋Š” Javascript์˜ superset์œผ๋กœ, ์ •์  type์„ ์ถ”๊ฐ€ํ•˜์—ฌ Javascript์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. Typescript๋Š” ๊ธฐ์กด Javascript ์ฝ”๋“œ์™€ ํ˜ธํ™˜๋˜๋ฉด์„œ๋„ ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋” ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ชฉ์ฐจโ€‹

ํฌ๊ฒŒ 4๊ฐ€์ง€๋กœ ๋‚˜๋ˆ„์–ด ์ •๋ฆฌํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ๋ฌธ๋ฒ•๊ณผ ์œ ํ˜•โ€‹

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—๋Š” ๋ณ€์ˆ˜์— ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • number: ์ˆซ์ž
  • string: ํ…์ŠคํŠธ
  • boolean: ์ฐธ ๋˜๋Š” ๊ฑฐ์ง“
  • any: ๋ชจ๋“  ์œ ํ˜•, ์œ ํ˜•์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ๊ฒฝ์šฐ

๋‹ค์Œ์€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ํƒ€์ž… ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

let firstName: string = "John";
let age: number = 30;
let isStudent: boolean = false;

arrayโ€‹

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ array์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค:

let numbers: number[] = [1, 2, 3];
let names: string[] = ["John", "Jane", "Bob"];

// ๋˜๋Š”

let numbers: Array<number> = [1, 2, 3];

tupleโ€‹

tuple์€ ๊ณ ์ •๋œ ๊ธธ์ด์˜ array์ž…๋‹ˆ๋‹ค. ๊ฐ ์š”์†Œ๋Š” ํŠน์ • ํƒ€์ž…์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let person: [string, number] = ["John", 30];

enumโ€‹

enum์€ ์ด๋ฆ„์ด ์žˆ๋Š” ์ƒ์ˆ˜ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค.

enum Color {
Red,
Green,
Blue,
}

let c: Color = Color.Green;

anyโ€‹

any๋Š” ๋ชจ๋“  ์œ ํ˜•์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. any๋Š” ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ธฐ ๋•Œ๋ฌธ์—, ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ์žƒ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

let notSure: any = 4;

notSure = "maybe a string instead";

notSure = false; // okay, definitely a boolean

functionโ€‹

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ function์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค:

function add(a: number, b: number): number {
return a + b;
}

voidโ€‹

void๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์ด ์—†๋Š” ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

function warnUser(): void {
console.log("This is my warning message");
}

null๊ณผ undefinedโ€‹

null๊ณผ undefined๋Š” ๊ฐ๊ฐ ์ž์‹ ์˜ ํƒ€์ž…์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ null๊ณผ undefined๋Š” ๋ชจ๋“  ํƒ€์ž…์˜ ํ•˜์œ„ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

let u: undefined = undefined;

let n: null = null;

neverโ€‹

never๋Š” ์ ˆ๋Œ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ๊ฐ’์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. never๋Š” ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function error(message: string): never {
throw new Error(message);
}

objectโ€‹

object๋Š” ์›์‹œ ํƒ€์ž…์„ ์ œ์™ธํ•œ ๋ชจ๋“  ํƒ€์ž…์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

declare function create(o: object | null): void;

create({ prop: 0 }); // OK

create(null); // OK

create(42); // Error

create("string"); // Error

create(false); // Error

create(undefined); // Error

Typesciprt ๊ฐœ๋…โ€‹

Type Inferenceโ€‹

Type Inference๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค.

let a = 1 + 2; // a๋Š” number ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.

let b = [1, null]; // b๋Š” (number | null)[] ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.

let c = "abc".substr(1); // c๋Š” string ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.

Type Assertionsโ€‹

Type Assertions๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ํŠน์ • ํƒ€์ž…์œผ๋กœ ํƒ€์ž…์„ ์ง€์ •ํ•˜๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค. Typescript๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ํƒ€์ž…์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€๋งŒ, ํƒ€์ž…์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์€ ๊ฐœ๋ฐœ์ž์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•ด, ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ "๋‚ด๊ฐ€ ์‹œํ‚ค๋Š” ๋Œ€๋กœ ํ•˜๋ผ"๋ผ๊ณ  ๋‹จ์–ธ(assert)ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length; // as ๋ฌธ๋ฒ•

// ๋˜๋Š”

let strLength: number = (<string>someValue).length; // JSX ๋ฌธ๋ฒ•์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

Literal Narrowingโ€‹

Literal Narrowing์€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์„ ์ถ•์†Œํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ํŠน์ •ํ•œ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

let x: 10 = 10; // x๋Š” 10์ด๋ผ๋Š” ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

Union Typesโ€‹

Union Types๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์—ฌ๋Ÿฌ ํƒ€์ž…์„ ํ•˜๋‚˜์˜ ํƒ€์ž…์œผ๋กœ ํ•ฉ์น˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

let x: number | string = 10; // x๋Š” number ๋˜๋Š” string ํƒ€์ž…์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

Type Guardsโ€‹

Type Guards๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํƒ€์ž…์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ํƒ€์ž…์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • typeof
  • instanceof
function isNumber(x: any): x is number {
return typeof x === "number"; // return x instanceof Number;
}

function isString(x: any): x is string {
return typeof x === "string"; // return x instanceof String;
}

function padLeft(value: string, padding: string | number) {
// "number"
if (isNumber(padding)) {
return Array(padding + 1).join(" ") + value;
}
// "string"
if (isString(padding)) {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}

Type Compatibilityโ€‹

Type Compatibility๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํƒ€์ž…์„ ํ˜ธํ™˜๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ํƒ€์ž… ํ˜ธํ™˜์„ฑ์€ ๊ตฌ์กฐ์  ํƒ€์ดํ•‘(structural typing)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์กฐ์  ํƒ€์ดํ•‘์€ ํƒ€์ž…์ด ๊ตฌ์กฐ์ ์œผ๋กœ ๊ฐ™์œผ๋ฉด ํ˜ธํ™˜๋œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

interface Named {
name: string; // name ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
}

class Person {
name: string; // name ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
}

let p: Named;

// ๊ตฌ์กฐ์  ํƒ€์ดํ•‘์ด string ํƒ€์ž…์„ ๊ฐ€์ง„ name ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค.

p = new Person();

Type Aliasesโ€‹

Type Aliases๋Š” ํƒ€์ž…์„ ์ƒˆ๋กœ์šด ์ด๋ฆ„์œผ๋กœ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

type Name = string;

type NameResolver = () => string;

type NameOrResolver = Name | NameResolver;

function getName(n: NameOrResolver): Name {
if (typeof n === "string") {
return n;
} else {
return n();
}
}

Interface์™€ Classโ€‹

Interfaceโ€‹

Interface๋Š” ๊ฐ์ฒด์˜ ๋ชจ์–‘์„ ์ •์˜ํ•˜์—ฌ ํŠน์ • ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๋„๋ก ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

interface User {
id: number;
name: string;
email: string;
}

const user: User = {
id: 1,
name: "John Doe",
email: "john@example.com",
};

Classโ€‹

Class๋Š” ํŠน์ • ๊ตฌ์กฐ์™€ ๋™์ž‘์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

class Animal {
name: string;

constructor(name: string) {
this.name = name;
}

speak(): void {
console.log(`My name is ${this.name}`);
}
}

const dog = new Animal("Buddy");
dog.speak(); // ์ถœ๋ ฅ : My name is Buddy

Module๊ณผ Namespaceโ€‹

Moduleโ€‹

Module์€ ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์บก์Šํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. Module์€ ๋ณ€์ˆ˜, ํ•จ์ˆ˜, ํด๋ž˜์Šค ๋“ฑ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

math.ts
export function add(a: number, b: number): number {
return a + b;
}
subtraction.ts
export function subtract(a: number, b: number): number {
return a - b;
}
index.ts
import { add } from "./math";
import { subtract } from "./subtraction";

console.log(add(1, 2)); // ์ถœ๋ ฅ : 3
console.log(subtract(5, 3)); // ์ถœ๋ ฅ : 2

Namespaceโ€‹

Namespace๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. Namespace๋Š” ์ด๋ฆ„ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ํ•จ๊ป˜ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค:

namespace Geometry {
export interface Point {
x: number;
y: number;
}

export function calculateDistance(p1: Point, p2: Point): number {
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
return Math.sqrt(dx * dx + dy * dy);
}
}

const point1: Geometry.Point = { x: 0, y: 0 };
const point2: Geometry.Point = { x: 3, y: 4 };
const distance: number = Geometry.calculateDistance(point1, point2);

console.log(distance); // Output: 5