JavaScript의 상위 집합(Superset)으로, 정적 타입(static type)을 지원하는 언어
JavaScript 코드에 타입 시스템과 클래스 기반 객체지향 프로그래밍(OOP) 기능을 추가한 언어.
.ts 확장자 사용| JavaScript의 한계 | TypeScript의 장점 |
|---|---|
| 동적 타입으로 인한 런타임 에러 | 컴파일 단계에서 타입 오류를 미리 탐지 |
| 자동완성 지원 부족 | 에디터에서 강력한 자동완성 및 인텔리센스 |
| 복잡한 프로젝트에서 구조적 제약 부족 | 인터페이스, 제네릭, 클래스 등으로 구조화 가능 |
정적 타입(Static Typing)
변수나 함수의 타입을 명시하여 오류를 사전에 방지함
let name : string = "이름";
let age : number = 25;
인터페이스와 타입 시스템
객체 구조를 명확히 정의하고, 정형화된 설계를 가능하게 함
interface User {
id : number;
name : string;
}
클래스 기반 객체지향 프로그래밍 지원
JavaScript의 ES6+ 클래스를 확장하고, public, private, readonly같은 접근 제어자를 지원함
class Animal {
constructor(private name: string) {}
speak() {
console.log(`${this.name} is speaking`);
}
}
제네릭(Generic)
함수나 클래스에서 유연하면서도 타입 안정성을 유지할 수 있음
function idenfity<T>(value: T) T {
return value;
}
열거형(Enum)
특정 값 집합을 명확하게 정의할 수 있음
enum Role {
Admin,
User,
Guest
}
유틸리티 타입 제공
Partial, Readonly, Pick, Omit 등 재사용성, 효율성을 높이는 타입 도구 제공
| 키워드 | 설명 |
|---|---|
type, interface | 타입 정의 |
enum | 열거형 |
class, extends | 클래스와 상속 |
public, private, protected | 접근 제어자 |
readonly | 읽기 전용 속성 |
as | 타입 단언 (Type Assertion) |
unknown, any, never, void | 특수 타입 |
T | 제네릭 타입 변수 |
? | 선택적 속성 / 매개변수 |
! | Non-null 단언 |
let userName = '유빈'; // ✅
let $price = 1000; // ✅
let _id = 'abc'; // ✅
let 1stName = 'Kim'; // ❌ 숫자로 시작
let let = '예약어'; // ❌ 예약어
let userAge = 25; // 변수
function getUserName() {} // 함수
class UserProfile {} // 클래스
interface UserData {} // 인터페이스
type UserId = number | string; // 타입 별칭
변수 선언 키워드
| 키워드 | 설명 |
|---|---|
let | 블록 범위, 재할당 가능 |
const | 블록 범위, 재할당 불가 (변경 불가능한 것이 아님에 주의) |
var | 함수 범위, 사용 지양 (hoisting 문제) |
변수 타입 지정 방법
변수에 타입을 명시하거나, 타입 추론에 맡길 수 있음
// 명시적 타입 지정
let age: number = 1;
let name: string = '리리';
let isActive: boolean = true;
// 타입 추론 (타입 생략 시 자동 추론)
let city = 'Seoul'; // string으로 추론
자주 사용하는 타입
| 타입 | 설명 | 예시 | |
|---|---|---|---|
number | 숫자 (정수, 실수) | let age: number = 30; | |
string | 문자열 | let name: string = '리리'; | |
boolean | 참/거짓 | let isValid: boolean = true; | |
any | 모든 타입 허용 (지양 권장) | let value: any = 10; | |
unknown | 정체 모를 타입 (런타임까지 미정) | let input: unknown; | |
null, undefined | 널 / 정의되지 않음 | let a: null = null; | |
void | 반환값 없음 (주로 함수에서 사용) | function log(): void {} | |
never | 절대 반환되지 않음 | function fail(): never { throw new Error(); } | |
object | 객체 | let user: object = { name: '유빈' }; | |
array | 배열 | let nums: number[] = [1, 2, 3]; | |
tuple | 고정된 타입/길이 배열 | let tuple: [string, number] = ['리리', 1]; | |
enum | 열거형 | enum Role { User, Admin } | |
union | 여러 타입 허용 | `let id: number | string = 'abc';` |
literal | 특정 값만 허용 | `let yes: 'Y' | 'N' = 'Y';` |
주의할 것
let user: { name: string; age: number } = {
name: '리리',
age: 1
};
let scores: number[] = [100, 90, 80];
let names: Array<string> = ['리리', '키키'];
실습해보려 코드를 몇 줄 짜고 출력해보았는데
npx ts-node test-1.ts
아무것도 출력되지 않았다.
한참동안 헤메다가 결국 tsx를 사용하는 방법을 찾았다.
왜 ts-node는 안됐고, tsx는 됐던걸까?
| 항목 | ts-node | tsx |
|---|---|---|
| 실행 방식 | TypeScript → JS → 실행 (VM 기반) | ESBuild 기반 즉시 실행 (빠름 + 간단) |
| 출력 처리 방식 | 내부적으로 process.stdout.write() 사용 | 표준 Node 실행처럼 console.log 직접 처리 |
| Node 최신 버전 대응 | 다소 느림, 버그 있음 | 매우 빠름, 최신 Node 대응 우수 |
| stdout 버그 | 있음 (특히 Node 18~22 + zsh 조합) | 없음 (stdout 버그 거의 없음) |
ts-node는 내부적으로 다음과 같이 작동한다.
1. TypeScript를 런타임에서 JavaScript로 변환
2. JS 코드를 Node.js VM (가상머신 컨텍스트) 내에서 실행
3. 출력은 process.stdout.write() 등을 통해 간접적으로 출력됨
-> 이 방법이 최신 Node.js의 스트림 처리 방식과 가끔 충돌하는 경우가 있다고 한다.
특히 mac에서 zsh, 로제타, 터미널 환경 설정 등이 함께 얽히면 출력 자체가 블로킹되거나 버퍼에 남아 표시되지 않는 문제가 발생할 수 있다.
tsx 설치하기
npm install -g tsx
실행
npx tsx test-1.ts
ts-node는 삭제해주었다.
npm uninstall -g ts-node
다시 돌아와서 찐 실습
// test-1.ts
// 가본 타입, 변수 선언하기
let username: string = "리리";
let age: number = 1;
let isMember: boolean;
let anyTest: any;
isMember = true;
anyTest = 123;
anyTest = { key: "value" };
console.log(username, age, isMember);
console.log("test : ", anyTest);
// 출력
리리 1 true
test : { key: 'value' }
add(a:number, b:number): number 작성하기logMessage(msg: string, user?: string)작성하기function add(a: number, b: number): number {
return a + b;
}
function logMessage(msg: string, user?: string): void {
if (user) {
console.log(`${user} syas : ${msg}`);
} else {
console.log(`someone says ${msg}`);
}
}
console.log("result : ", add(3, 8));
logMessage("먀옹", "리리");
logMessage("거 개 짖는 소리 좀 안 나게 해라");
// 출력
result : 11
리리 syas : 먀옹
someone says 거 개 짖는 소리 좀 안 나게 해라
Product 인터페이스 정의하기.User 인터페이스를 받아 인사 메시지를 출력하는 함수 작성하기interface Product {
id: number;
title: string;
price: number;
}
interface User {
id: number;
name: string;
}
function logined(user: User): void {
console.log(`${user.name}님이 로그인하셨습니다.`);
}
const user: User = { id: 1, name: "리리" };
logined(user);
// 출력
리리님이 로그인하셨습니다.
Car 클래스를 만들고 model, year, drive() 메서드 정의하기Employee 클래스에서 private salary 속성 정의하기class Car {
model: string;
year: number;
constructor(model: string, year: number) {
this.model = model;
this.year = year;
}
drive(): void {
console.log(`${this.model} ${this.year} is driving`);
}
}
class Employee {
private salary: number;
constructor(salary: number) {
this.salary = salary;
}
getSalary(): number {
return this.salary;
}
}
const car = new Car("Tesla", 2025);
car.drive();
const emp = new Employee(5000);
console.log("salary is : ", emp.getSalary());
// 출력
Tesla 2025 is driving
salary is : 5000
getFirstElement<T>(arr: T[]): T 작성하기Stack<T> 클래스를 만들어 push, pop 메서드 구현하기function getFristElement<T>(arr: T[]): T {
return arr[0];
}
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
size(): number {
return this.items.length;
}
}
const numbers = [1, 2, 3];
console.log(getFristElement(numbers));
const stack = new Stack<String>();
stack.push("a");
stack.push("b");
console.log("pop :", stack.pop());
console.log("size : ", stack.size());
// 출력
1
pop : b
size : 1
function func1(value: string | number): string | number {
if (typeof value === "string") {
return value.toLocaleUpperCase();
} else {
return value * value;
}
}
console.log(func1("abcde"));
console.log(func1(3));
// 출력
ABCDE
9
요일을 enum으로 정의하고, 해당 요일이 주말이면 "쉬세요!" 평일이면 "일해요!"를 출력하는 함수를 작성하기
enum days {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
}
function getMsg(day: days): string {
switch (day) {
case days.Sunday:
case days.Saturday:
return "쉬세요!";
default:
return "일해요!";
}
}
console.log(getMsg(days.Sunday));
console.log(getMsg(days.Monday));
// 출력
쉬세요!
일해요!