본 도구에서 사용하는 오픈소스 라이브러리

본 도구의 코드에는 1개의 오픈소스 라이브러리가 포함되어 있습니다.

TypeScript 빠른 참조 — 간결한 참고서

TypeScript 5 문법, 타입 시스템과 가장 자주 쓰는 관용 표현의 빠른 참조 매뉴얼로, 일상 시나리오의 약 80%를 다룹니다.

TS

TypeScript TypeScript 5.x

ECMAScript + 타입 · 다중 패러다임 · 구조적 · 정적(점진적) 타입 · JS 기반

추천 학습 경로

먼저 컴파일 환경(tsc/tsconfig)을 설정하고 TS가 JS의 상위 집합임을 이해함 → 기본 타입 표기, 유니온 타입과 인터페이스 마스터 → 타입 시스템 심화(제네릭, 타입 가드, 타입 조작) → class와 모듈로 코드 조직화 → 비동기와 DOM/Node 타입 처리 → 마지막으로 필요에 따라 빌드 설정, 테스트, 디버깅을 조회. FAQ 섹션은 나중에 돌아와 함정을 피할 때 적합함.

1.Hello World와 빌드 환경

TypeScript를 빌드하고 실행하며, tsc, tsconfig, 그리고 타입 검사 흐름을 이해한다.

최소 프로그램

TS는 JS의 상위 집합이다. 합법적인 JS는 모두 합법적인 TS이며, 타입 표기를 추가한 뒤 tsc로 컴파일하면 JS가 된다.

1
2
3
4
5
6
// hello.ts
const message: string = 'Hello, world!';
console.log(message);
// 型注釈:変数名の後の : string
// $ npx tsc hello.ts # コンパイルして hello.js を生成
// $ node hello.js

tsc 컴파일

tsc는 .ts를 .js로 컴파일한다. --noEmit은 타입 검사만 수행하고 출력하지 않으며, --watch는 변경을 감시하고, --strict는 엄격 모드다.

1
2
3
4
5
// $ npx tsc app.ts # 単一ファイルをコンパイル
// $ npx tsc --noEmit # 型チェックのみ
// $ npx tsc --watch # 監視して自動コンパイル
// $ npx tsc --strict # 厳格な型チェック
// $ npx tsc --outDir dist # 出力ディレクトリ

tsconfig.json

tsconfig.json에서 컴파일을 설정한다. target, module, strict, outDir 등을 지정하며, npx tsc는 이를 자동으로 읽는다.

1
2
3
4
5
6
7
8
9
10
11
12
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true, // 厳格モード
"outDir": "dist",
"sourceMap": true // デバッグ用ソースマップ
},
"include": ["src"]
}
// tsc --init でデフォルト設定を生成

TS 직접 실행

tsx/ts-node을 사용하면 TS를 별도 컴파일 없이 바로 실행할 수 있다. Node 22는 --experimental-strip-types를 네이티브로 지원한다.

1
2
3
4
5
// $ npx tsx script.ts # TS を直接実行
// $ npx ts-node script.ts # 旧方式
// Node 22+:
// $ node --experimental-strip-types script.ts
// 開発スクリプトは tsx が一般的、本番は tsc でコンパイルして実行

엄격 모드

strict: true는 모든 엄격 검사를 활성화한다. null 검사, 암묵적 any에 대한 오류, 사용하지 않는 변수에 대한 경고 등이 포함된다. 새 프로젝트에서는 반드시 켜야 한다.

1
2
3
4
5
6
7
8
// strict には以下が含まれます:
// 1. strictNullChecks null を通常の型に代入不可
// 2. noImplicitAny 引数に型がない場合にエラー
// 3. noUnusedLocals 未使用の変数でエラー
function greet(name: string) { // 明示的な型
return 'Hi ' + name;
}
// strict を有効にしない場合、name は暗黙の any となりエラーにならない

TS와 JS의 관계

TS는 컴파일 시점에 타입을 검사하며, 컴파일된 JS에는 타입 정보가 없다. 타입은 컴파일 시점에만 존재하고, 런타임에는 사라진다.

1
2
3
4
5
6
7
8
interface User {
name: string;
age: number;
}
const u: User = { name: 'Nick', age: 30 };
// コンパイル結果(型は削除される):
// const u = { name: 'Nick', age: 30 };
// 型エラーはコンパイル時に検出され、実行には影響しない

의존성과 타입 패키지

라이브러리에는 타입 정의가 필요하다. @types/*는 DefinitelyTyped 커뮤니티 타입 패키지이며, typescript는 컴파일 도구 의존성이다.

1
2
3
4
5
6
// $ npm i -D typescript @types/node
// $ npm i -D @types/express # コミュニティ型
// ライブラリに付属する型:
// axios は直接 export するため、@types 不要
// // @ts-ignore コメント:次の行のチェックをスキップ(慎重に)
// import axios from 'axios'; 型定義あり

에디터 통합

VS Code는 TS를 기본 지원한다. 호버로 타입을 확인하고, 오류는 빨간 밑줄로 표시되며, 자동 완성 및 리팩토링을 제공한다. 오류 메시지는 그대로 표시된다.

1
2
3
4
5
6
7
// VS Code ショートカット:
// ホバー:型を表示
// クイック修正:Ctrl+. (Cmd+.)
// シンボルの名前変更:F2
// 定義へジャンプ:F12
// 型エラーは Problems パネルに表示
// 設定:ワークスペースの tsconfig には `tsc` のバージョンを合わせる必要あり

2.변수와 타입 표기

타입 표기, 타입 추론, 유니온 타입, any/unknown 그리고 타입 단언.

타입 표기

변수명 뒤에 : 타입 형식으로 타입을 표기한다. 표기 후 타입이 고정되며, 다른 타입을 대입하면 컴파일 오류가 발생한다.

1
2
3
4
5
6
const name: string = 'Nick';
let age: number = 30;
const isAdmin: boolean = true;
// エラー例:
// age = 'thirty'; // 型エラー
// 初期化後は型推論が効くため明示不要

타입 추론

TS는 초기화 값으로부터 타입을 추론하므로 대부분의 경우 명시적 표기가 필요 없다. 복잡한 타입은 명시적 인터페이스를 권장한다.

1
2
3
4
5
6
7
8
const name = 'Nick'; // string と推論
let count = 42; // number
const arr = [1, 2, 3]; // number[]
const obj = { a: 1 }; // { a: number }
// 代入時のユニオン推論:
let status = 'idle' as const;
// 複雑なシナリオでは明示注釈が分かりやすい:
let data: Map<string, User> = new Map();

유니온 타입

| 유니온 타입은 "또는"을 나타낸다. 예를 들어 string | number는 둘 다 허용한다. 멤버에 접근하려면 먼저 타입 가드가 필요하다.

1
2
3
4
5
6
7
8
9
10
11
12
function print(value: string | number) {
// ユニオン型は共通メンバーのみアクセス可
console.log(value.toString());
// 分岐処理:
if (typeof value === 'string') {
console.log(value.toUpperCase()); // string
} else {
console.log(value.toFixed(2)); // number
}
}
// リテラルユニオン:
type Dir = 'up' | 'down' | 'left' | 'right';

any와 unknown

any는 타입 검사를 비활성화하므로(피해야 함), unknown은 미지의 값을 나타낸다(가드 후에만 사용 가능). 외부 데이터를 안전하게 처리할 때는 unknown을 사용한다.

1
2
3
4
5
6
7
8
9
let risky: any = 'text'; // any:チェックなし、慎重に
risky.method(); // コンパイルは通るがランタイムでクラッシュの可能性
// unknown:安全
let data: unknown = getApi();
if (typeof data === 'string') {
console.log(data.length); // ガード後に使用可
}
// unknown のアサーション:data as string
// any より unknown を優先

타입 단언

as 단언은 컴파일러보다 자신이 더 잘 안다고 선언하는 것이다. 단언은 런타임을 바꾸지 않으며, 컴파일 시점의 선언일 뿐이다. 남용하면 오류를 가린다.

1
2
3
4
5
6
7
const el = document.getElementById('btn') as HTMLButtonElement;
// 二重アサーションは非推奨(落とし穴):
// const n = value as unknown as number;
// より安全:まずガード、それからアサーション
const json = JSON.parse(text) as User[];
// as const:リテラルへの絞り込み
const modes = ['dev', 'prod'] as const;

non-null 단언

! 접미사는 값이 null/undefined가 아님을 단언한다. 확실할 때만 사용해야 하며, 그렇지 않으면 런타임에 충돌할 수 있다.

1
2
3
4
5
6
7
8
9
let name: string | null = getMaybe();
const len = name!.length; // 非 null アサーション(リスクあり)
// より安全な書き方:
if (name) {
const l2 = name.length;
}
// または null 合体:
const l3 = name?.length ?? 0;
// 非 null アサーションはコンパイル時の約束、ランタイムで null だとクラッシュ

리터럴 타입

리터럴 타입은 타입을 구체적인 값으로 한정한다. 예를 들어 'up', 42, true 등이 있다. 유니온과 함께 사용해 옵션을 열거한다.

1
2
3
4
5
6
7
8
let direction: 'up' | 'down' = 'up';
// direction = 'sideways'; // エラー:ユニオンに含まれない
const yes: true = true;
// オブジェクトプロパティの絞り込み:
const config = {
mode: 'production',
} as const; // mode: 'production' リテラル
// as const でオブジェクトメンバーを読み取り専用リテラル型に

구조 분해와 타입

구조 분해 할당에서도 타입이 유지된다. 함수 매개변수를 구조 분해할 때는 매개변수 객체 전체의 타입을 표기해야 한다.

1
2
3
4
5
6
7
8
9
10
interface User { name: string; age: number; }
const { name, age }: User = getUser();
// 関数の引数で分割代入:
function show({ name, age }: User) {
console.log(name, age);
}
// 配列の分割代入:
const [first, second] = [1, 2] as const;
// オプションプロパティの分割代入:
const { name = 'guest' }: { name?: string } = data;

3.타입 시스템

기본 타입, 객체/배열/튜플, 인터페이스, 제네릭, 타입 별칭 그리고 타입 조작.

기본 타입

string, number, boolean, null, undefined, void, symbol, bigint로 구성된 기본 타입 집합이다.

1
2
3
4
5
6
7
8
const s: string = 'text';
const n: number = 42;
const b: boolean = true;
const v: void = undefined; // 戻り値なしの関数
const nl: null = null;
const u: undefined = undefined;
const sym: symbol = Symbol('id');
const big: bigint = 10n;

배열과 튜플

number[]는 배열, [string, number]는 튜플(고정 길이·고정 순서), readonly는 읽기 전용 배열이다.

1
2
3
4
5
6
7
8
9
const nums: number[] = [1, 2, 3];
const strs: Array<string> = ['a', 'b']; // ジェネリック構文
// タプル:
let pair: [string, number] = ['age', 30];
// pair[0] = 42; // エラー:型が一致しない
// 読み取り専用配列:
const fixed: readonly number[] = [1, 2];
// fixed.push(3); // エラー:読み取り専用
// オプショナルタプル要素:type T = [string, number?]

객체 타입

객체 타입은 형태를 묘사한다. 속성, 선택적 ?, 읽기 전용 readonly, 메서드 시그니처 등을 포함한다.

1
2
3
4
5
6
7
8
9
10
11
12
interface Point {
readonly x: number; // 読み取り専用
y: number;
label?: string; // オプショナル
}
const p: Point = { x: 1, y: 2 };
// p.x = 10; // エラー:readonly
// メソッド:
interface Greeter {
greet(name: string): string;
// または greet: (name: string) => string;
}

interface와 type

interface는 객체 형태를 정의하며(확장 가능), type 별칭은 더 유연하다(유니온/교차/튜플). 일반적으로는 interface를 우선 사용한다.

1
2
3
4
5
6
7
8
9
10
11
interface User {
name: string;
}
// interface はマージ/継承可能:
interface Admin extends User {
permissions: string[];
}
// type エイリアス:
type ID = string | number; // ユニオン
type Pair = [string, number]; // タプル
type Shape = { area: number } & { color: string }; // 交差

열거형

enum은 명명된 상수 집합이다. 숫자 열거형, 문자열 열거형, const enum 등이 있으며, 문자열 열거형이 더 자주 쓰인다.

1
2
3
4
5
6
7
8
9
10
11
12
13
enum Color {
Red, // 0
Green, // 1
Blue, // 2
}
enum Status {
Active = 'active',
Inactive = 'inactive',
}
const c: Color = Color.Green;
const s: string = Status.Active; // 'active'
// 逆引きマッピング:Color[0] === 'Red'(数値 enum)
// 型だけ欲しい場合:type S = 'active' | 'inactive'

제네릭

제네릭은 타입을 매개변수화한다. T는 타입 매개변수이며, 함수/클래스/인터페이스를 범용적으로 재사용할 수 있게 하고 컴파일 시점에 결정된다.

1
2
3
4
5
6
7
8
9
10
11
function identity<T>(value: T): T {
return value;
}
const s = identity('hello'); // string
const n = identity(42); // number
// ジェネリック interface:
interface Box<T> {
value: T;
}
const box: Box<number> = { value: 42 };
// 複数パラメータ:function pair<A, B>(a: A, b: B)

keyof와 인덱스

keyof는 객체 키의 유니온을 얻고, T[K]는 인덱스 접근이며, 매핑 타입은 타입 조작의 핵심 도구다.

1
2
3
4
5
6
7
8
9
10
interface User { name: string; age: number; }
type Keys = keyof User; // 'name' | 'age'
// インデックスアクセス:
type NameType = User['name']; // string
// マップ型:
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
// Partial<T>、Required<T>、Pick<T,K> は組み込みユーティリティ
// 一部オプショナル:type PartialUser = Partial<User>

내장 유틸리티 타입

Partial, Omit, Pick, Record, Exclude, ReturnType 등의 매핑 타입이 일반적인 변환을 단순화한다.

1
2
3
4
5
6
7
type PartialUser = Partial<User>; // すべてオプショナル
type PickName = Pick<User, 'name'>; // name のみ取得
type NoAge = Omit<User, 'age'>; // age を除外
type Rec = Record<string, number>; // キーと値のマッピング
type WithoutZero = Exclude<0 | 1 | 2, 0>; // 1 | 2
type R = ReturnType<typeof fn>; // 関数の戻り型
// Parameters<typeof fn> は引数の型

템플릿 리터럴 타입

템플릿 문자열 문법으로 문자열 타입을 구성한다. 유니온과 결합하여 순열 조합을 생성할 수 있으며, 문자열 파싱을 타입 수준에서 구현하는 기법이다.

1
2
3
4
5
6
7
8
type Event = `on${'Click' | 'Hover'}`;
// Event = 'onClick' | 'onHover'
type Size = `${'small' | 'large'}-${number}`;
// Size = 'small-1' | 'large-2' ...
// 文字列からの抽出:
// type Extracted = 'a:b'.split<'a:b', ':'>; // 型レベルの split
// 簡単な文字列パース:
// type First = 'abc' extends `${infer F}bc` ? F : never; // 'a'

4.타입 가드와 null 값

타입 가드, 타입 좁히기, 옵셔널 체이닝, null 처리 그리고 참조 의미.

타입 가드

typeof, instanceof, in으로 유니온 타입을 좁힌다. 분기 내부에서 타입이 자동으로 좁아진다.

1
2
3
4
5
6
7
8
9
10
11
function f(v: string | number | Date) {
if (typeof v === 'string') {
v.toUpperCase(); // string
} else if (v instanceof Date) {
v.getTime(); // Date
} else {
v.toFixed(2); // number
}
}
// in ガード:
if ('permissions' in user) { /* Admin */ }

타입 좁히기

가드 이후 타입은 해당 범위 내에서 좁아진다(narrowing). null 검사나 truthy 검사 모두 타입을 좁힌다.

1
2
3
4
5
6
7
8
9
10
11
let value: string | null = getMaybe();
if (value) {
value.length; // string(絞り込み)
}
// 真偽値での絞り込み:
function f(s: string | undefined) {
s ?? console.log('missing'); // null 合体での絞り込み
}
// null チェック後:
value = null;
if (value === null) return; // 以降 value は非 null

식별 유니온

식별 유니온은 공통 판별 필드(kind/type)를 공유하며, switch 이후 타입이 정확하게 좁아진다. 상태 모델링에 적합하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; side: number };
function area(s: Shape): number {
switch (s.kind) {
case 'circle': return Math.PI * s.radius ** 2;
case 'square': return s.side * s.side;
// 網羅性チェック:
default: {
const _exhaustive: never = s;
return _exhaustive;
}
}
}

옵셔널 체이닝과 nullish 병합

?.는 안전한 접근, ??는 nullish에 대한 기본값, ??=는 기본값 할당이다. 체인 형태의 깊은 접근으로 null로 인한 충돌을 방지한다.

1
2
3
4
5
6
7
8
9
const name = user?.profile?.name ?? 'guest';
const count = data?.items?.length ?? 0;
// null 合体代入:
let settings = getConfig();
settings ??= { theme: 'dark' };
// オプショナル呼び出し:
callback?.();
// ?? と || の違い:
// 0 ?? 'x' は 0;0 || 'x' は 'x'

null과 undefined

strictNullChecks가 켜져 있으면 null/undefined는 일반 타입에 대입할 수 없다. 명시적 유니온이나 명시적 처리가 필요하다.

1
2
3
4
5
6
7
8
9
let name: string | null = null; // ユニオンに null を含む
let title: string | undefined;
// 関数の戻り値が null 可能性あり:
function find(): User | null {
return Math.random() > 0.5 ? null : { name: 'x' };
}
const u = find();
if (u) { u.name; } // 絞り込み後にアクセス
// 安全なアサーション:u!.name または u ?? { name: '?' }

참조 의미

TS는 JS의 참조 의미를 바꾸지 않는다. 객체는 참조로 공유되고 배열은 얕은 복사된다. 타입은 그 형태만 기술할 뿐이다.

1
2
3
4
5
6
7
8
9
const a = { x: 1 };
const b = a; // 参照共有
b.x = 99;
console.log(a.x); // 99
// コピーしてもシャローコピー:
const c = { ...a };
c.x = 1; // a.x は不変
// TS の型は不変性を保証しない(readonly 必要)
// 深い凍結は as const + ライブラリで

사용자 정의 타입 가드

is 문법으로 함수가 타입 가드임을 선언한다. boolean을 반환하며 매개변수의 타입을 좁힌다. 배열 필터링에 자주 쓰인다.

1
2
3
4
5
6
7
8
9
function isString(v: unknown): v is string {
return typeof v === 'string';
}
const values: unknown[] = ['a', 1, 'b', null];
const strs = values.filter(isString);
// strs の型は string[](ガードが効く)
// アロー関数での書き方:
const s2 = values.filter(
(v): v is string => typeof v === 'string');

단언 함수

asserts 단언 함수는 불변 조건을 선언한다. 반환 타입은 void이지만 호출 후 타입이 좁아지며, 오류를 던지면 실행이 중단된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function assertString(v: unknown): asserts v is string {
if (typeof v !== 'string') {
throw new Error('期望 string');
}
}
function process(v: unknown): void {
assertString(v);
v.toUpperCase(); // string に絞り込まれる
}
// 無条件アサーション:
function assert(cond: unknown): asserts cond {}
// 値のアサーション:
function assertNonNull<T>(v: T): asserts v is NonNullable<T> {}
// ランタイム不変条件 + 型絞り込みの二重保険

5.제어 흐름

분기, 반복, switch와 타입 좁히기의 조합.

if / else

if/else 분기에 타입 가드를 결합한다. 조건식이 변수의 타입을 좁힌다.

1
2
3
4
5
6
7
8
9
function describe(v: string | number) {
if (typeof v === 'string') {
return `字符串: ${v.toUpperCase()}`;
} else {
return `数字: ${v.toFixed(2)}`;
}
}
// 多分岐 else-if + ガードで段階的に絞り込み
// truthy チェック:if (value) で非空に絞り込み

switch와 완전성 검사

switch는 식별 유니온을 처리한다. default 분기에서 never를 사용해 모든 경우가 처리되었는지 검사할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
type Action =
| { type: 'add'; n: number }
| { type: 'reset' };
function reducer(a: Action) {
switch (a.type) {
case 'add': return a.n;
case 'reset': return 0;
default: {
const exhaustive: never = a; // 分岐不足はコンパイルエラー
return exhaustive;
}
}
}

반복문

for, for...of, while로 순회한다. 배열은 for...of로 반복하고, 인덱스가 필요하면 for 또는 entries를 사용한다.

1
2
3
4
5
6
7
8
9
for (let i = 0; i < 10; i++) { }
for (const item of items) { }
for (const [i, v] of items.entries()) {
console.log(i, v);
}
let n = 0;
while (n < 5) { n++; }
// オブジェクトキーの反復:
for (const key of Object.keys(obj) as (keyof typeof obj)[]) { }

삼항 연산자와 타입

삼항 연산자의 양쪽 분기 타입이 유니온된다. 조건에 따라 다른 타입이 반환되면 결과는 유니온 타입이 된다.

1
2
3
4
5
6
const result = cond ? 'yes' : 0;
// result の型は 'yes' | 0(リテラルユニオン)
// 型を統一したい場合は明示注釈:
const msg: string = cond ? 'yes' : String(0);
// ネストした三項は可読性が悪いのでガードを使う
// null 値:v ?? fallback

break와 continue

continue는 현재 반복을 건너뛰고, break는 종료하며, 레이블이 있는 break/continue는 중첩을 제어합니다.

1
2
3
4
5
6
7
8
9
10
11
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) continue;
if (i > 7) break;
}
outer:
for (const a of list) {
for (const b of a.items) {
if (b.done) continue outer;
}
}
// 型は変わらず、純粋な制御フロー

조기 반환

가드 절로 일찍 return하면 중첩이 줄어듭니다. null 체크 후에는 타입이 좁혀집니다.

1
2
3
4
5
6
7
8
function process(u: User | null) {
if (u === null) return; // 早期リターン
if (u.age < 18) return;
console.log(u.name); // 非 null に絞り込まれている
}
// 複数のガードでメインロジックを平坦に
// null 合体で早期にデフォルト値を:
const name = u?.name ?? 'guest';

do...while

do...while은 본문을 먼저 한 번 실행한 뒤 조건을 검사합니다. 최소 한 번은 실행해야 하는 반복에 씁니다. 타입은 관여하지 않습니다.

1
2
3
4
5
6
7
8
9
10
11
let attempts = 0;
do {
attempts++;
const ok = tryOnce();
if (ok) break;
} while (attempts < 3);
// 最低 1 回実行し、その後条件を判定
// while:先に判定してから実行(0 回もあり得る)
// 使用シーン:
// リトライ、メニュー選択、入力バリデーション
// 無限ループに注意:条件は最終的に false になる必要あり

객체 순회

Object.keys는 객체의 키를 순회합니다. 타입 단언에 keyof를 쓰면 안전합니다. 값을 순회할 때는 Object.values를 사용합니다.

1
2
3
4
5
6
7
8
9
10
11
const config = { host: 'x', port: 3000 };
// キーの反復(アサーション必要):
for (const key of Object.keys(config) as (keyof typeof config)[]) {
console.log(key, config[key]);
}
// 値の反復:
for (const value of Object.values(config)) { }
// キーと値のペア:
for (const [k, v] of Object.entries(config)) { }
// 型の注意点:
// Object.keys は string[] を返すため、アサーション後に安全にアクセス

6.함수

함수 타입 표기, 선택/기본 매개변수, 오버로드, rest 매개변수, this.

함수 타입

함수 타입 표기: 매개변수 타입과 반환 타입. 화살표 함수의 타입과 함수 선언문은 동등합니다.

1
2
3
4
5
6
7
8
9
10
11
// 関数宣言:
function add(a: number, b: number): number {
return a + b;
}
// アロー関数:
const add = (a: number, b: number): number => a + b;
// 関数型の変数:
type Fn = (a: number, b: number) => number;
const f: Fn = add;
// void 戻り値:
function log(msg: string): void { console.log(msg); }

선택 매개변수와 기본 매개변수

?는 선택 매개변수, =는 기본 매개변수입니다. 기본 매개변수는 암묵적으로 선택입니다. 선택 매개변수는 필수 매개변수 뒤에 와야 합니다.

1
2
3
4
5
6
7
8
9
10
11
function greet(name: string, title?: string): string {
return title ? `${title} ${name}` : name;
}
// デフォルト引数:
function mul(a: number, b = 2): number {
return a * b;
}
mul(3); // 6
// デフォルト引数は省略可能
// オプショナル引数は後ろに配置:
// greet('Nick', undefined) も可

rest 매개변수

...rest는 개수가 정해지지 않은 매개변수를 배열로 수집합니다. rest 매개변수는 배열 타입으로 표기해야 합니다.

1
2
3
4
5
6
7
8
9
function sum(...nums: number[]): number {
return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6
// ジェネリック rest でタプルを保持:
function tuple<T extends unknown[]>(...args: T): T {
return args;
}
const t = tuple(1, 'a', true); // [number, string, boolean]

오버로드 시그니처

오버로드: 여러 시그니처 선언 + 하나의 구현. 호출 시 시그니처와 매칭됩니다. 매개변수 조합에 따라 반환 타입을 제약합니다.

1
2
3
4
5
6
7
8
function pick(obj: Record<string, unknown>, key: string): unknown;
function pick(obj: number[], index: number): number;
function pick(obj: any, key: string | number): unknown {
return obj[key];
}
// 実装シグネチャは外部から見えない
// オーバーロードは順にマッチ、緩い型は最後に
// 戻り値型が異なるケース:DOM API 型でよく使われる

제네릭 함수

제네릭 매개변수 제약: T extends 제약조건. 제약으로 타입을 제한한 뒤 그 제약 타입의 멤버를 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
function first<T extends string | number[]>(arr: T): T[number] {
return arr[0];
}
const s = first('hello'); // string
const n = first([1, 2, 3]); // number
// 制約付き呼び出し:
function getLen<T extends { length: number }>(v: T): number {
return v.length;
}
// 複数ジェネリック:<K, V extends keyof K>

this 타입

this 매개변수로 this 타입을 표기합니다. 메서드 체인은 this를 반환해 체이닝을 구현합니다. 화살표 함수는 this를 바인딩하지 않습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Builder {
private items: string[] = [];
add(item: string): this {
this.items.push(item);
return this; // チェーン
}
}
const b = new Builder().add('a').add('b');
// 明示的な this パラメータ(先頭に):
function log(this: { name: string }) {
console.log(this.name);
}
// アロー関数は外側の this を継承

콜백과 함수 매개변수

콜백 함수를 매개변수로 사용: 함수 타입으로 표기합니다. 배열 고차 함수 map/filter/reduce의 타입 추론.

1
2
3
4
5
6
7
8
9
function withLog(fn: (n: number) => number) {
return fn(42);
}
withLog(n => n * 2); // 引数型は自動推論
// 配列の高階関数:
const doubled = [1, 2, 3].map(n => n * 2);
const evens = [1, 2, 3, 4].filter(n => n % 2 === 0);
const total = [1, 2, 3].reduce((acc, n) => acc + n, 0);
// コールバックの this 型に注意、ロストしないように

함수 제약 팁

매개변수 유니언 좁히기, 선택적 콜백, 반환 추론. 함수 매개변수에는 구체적인 클래스보다 인터페이스를 쓰는 편이 낫습니다.

1
2
3
4
5
6
7
8
9
10
function handle(v: string | number, cb?: (r: string) => void) {
const r = typeof v === 'string' ? v.toUpperCase() : String(v);
cb?.(r); // オプショナルコールバック
}
// 引数には interface(構造的型):
interface HasId { id: number }
function findById<T extends HasId>(arr: T[], id: number): T | undefined {
return arr.find(x => x.id === id);
}
// 構造的型:形状が合えばよく、同一インスタンスでなくてよい

7.문자열

템플릿 문자열, 자주 쓰는 메서드, 정규식과 문자 처리.

템플릿 문자열

백틱 템플릿 문자열: ${}로 보간하고 여러 줄을 그대로 유지합니다. 타입은 여전히 string입니다.

1
2
3
4
5
6
7
8
9
10
11
12
const name = 'Nick';
const greeting = `Hello, ${name}!`;
// 複数行:
const lines = `
line 1
line 2
`;
// 式:
const total = `Sum: ${1 + 2}`;
// テンプレートリテラル型:
// type T = `id-${string}`
// 型は依然として string、テンプレートはシンタックスシュガー

자주 쓰는 메서드

slice/substring으로 부분 문자열을 잘라내고, toUpperCase로 변환하며, split으로 나누고, includes/startsWith로 조회하며, replace로 교체합니다.

1
2
3
4
5
6
7
8
9
const s = 'TypeScript';
const sub = s.slice(0, 4); // 'Type'
const upper = s.toUpperCase(); // 'TYPESCRIPT'
const parts = s.split(''); // 文字配列
s.includes('Script'); // true
s.startsWith('Type'); // true
s.endsWith('t'); // true
const r = 'a-b-c'.replace(/-/g, '_'); // 'a_b_c'
const padded = '7'.padStart(3, '0'); // '007'

템플릿 리터럴 타입

타입 수준 템플릿 문자열: ${}로 타입을 이어 붙입니다. infer로 문자열 구조를 추출해 추론합니다.

1
2
3
4
5
6
7
8
type Route = `/users/${string}/profile`;
const good: Route = '/users/123/profile';
// 型レベルの抽出:
type ExtractId<S extends string> =
S extends `/users/${infer Id}/profile` ? Id : never;
type Id = ExtractId<'/users/42/profile'>; // '42'
// 大文字変換:Uppercase<T>、Lowercase<T>
// 組み合わせ:type All = `${'a'|'b'}${'1'|'2'}` // 'a1'|'a2'|'b1'|'b2'

문자와 코드 포인트

length는 UTF-16 코드 유닛 수입니다(이모지는 둘로 계산됨). 코드 포인트를 순회할 때는 for...of 또는 Array.from을 사용합니다.

1
2
3
4
5
6
7
8
9
const emoji = '👋';
console.log(emoji.length); // 2(サロゲートペア)
console.log([...emoji].length); // 1
const s = 'abc';
for (const ch of s) { } // コードポイント単位
// コードポイントアクセス:
const first = Array.from(s)[0];
// charCodeAt/fromCodePoint でコードポイントを処理:
String.fromCodePoint(128075); // '👋'

정규식

RegExp로 매칭과 교체를 합니다. match는 캡처 그룹 배열을 반환하고, matchAll은 전역 순회합니다. 타입 수준에서 RegExp는 고정되어 있습니다.

1
2
3
4
5
6
7
8
9
10
11
const re = /(\w+)@(\w+)/g;
const all = s.matchAll(re);
for (const m of all) {
console.log(m[1], m[2]); // キャプチャグループ
}
// キャプチャ付き置換:
const r = '2026-01-01'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3/$2/$1');
// 非 null アサート:
const match = s.match(/(\w+)@/);
if (match) { console.log(match[1]); }

로케일과 비교

localeCompare로 로케일 비교, toLocaleLowerCase로 로케일 변환, Intl로 숫자/날짜 포맷을 지정합니다.

1
2
3
4
5
6
const arr = ['ä', 'a', 'z'].sort((a, b) => a.localeCompare(b, 'zh'));
const num = (1234.5).toLocaleString('zh-CN'); // '1,234.5'
const date = new Date().toLocaleDateString('zh-CN');
// Intl.NumberFormat:
const nf = new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' });
// ロケール一覧:Intl.supportedValuesOf('language')

이스케이프 문자

문자열 이스케이프: \n 줄바꿈, \t 탭, \\ 백슬래시, \u 코드 포인트. 작은따옴표와 큰따옴표 모두에서 이스케이프합니다.

1
2
3
4
5
6
7
8
9
10
const nl = '第一行\n第二行';
const tab = 'a\tb'; // a スペースタブ b
const backslash = 'C:\\path'; // C:\path
const quote = 'He said \'hi\'';
const uni = '\u4e2d'; // '中'
const code = '\u{1F600}'; // emoji コードポイント
// テンプレート文字列はシングルクォート/ダブルクォートのエスケープ不要
const tmpl = `She said "hi" and 'bye'`;
// よく使う:\n 改行 \t インデント \\ パス
// JSON 出力ではクォートをエスケープする必要あり

뒤집기와 비교

문자열을 뒤집을 때는 split과 배열을 사용하고, 공백을 제거하며, 중복을 없앱니다. 비교에는 localeCompare 또는 정규화된 비교를 사용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
const s = 'hello';
// 反転:
const rev = [...s].reverse().join(''); // 'olleh'
// 先頭末尾の空白を除去:
const t = ' text '.trim();
// すべての空白を除去:
const compact = s.replace(/\s+/g, '');
// 繰り返し:'ab'.repeat(3) // 'ababab'
// 回文判定:
const isPalindrome = s === [...s].reverse().join('');
// 正規化比較(大文字小文字を無視):
s.toLowerCase() === 'HELLO'.toLowerCase()

8.컬렉션과 객체

배열, 객체, Map/Set과 불변 업데이트 패턴.

배열 연산

push/pop은 끝쪽, unshift/shift는 앞쪽, splice는 추가/삭제, slice는 복사, includes/indexOf는 조회.

1
2
3
4
5
6
7
8
9
const arr = [1, 2, 3];
arr.push(4); // [1,2,3,4]
const last = arr.pop(); // 4
arr.unshift(0); // [0,1,2,3]
const first = arr.shift(); // 0
const removed = arr.splice(1, 1); // 削除
const copy = arr.slice(); // シャローコピー
arr.includes(2);
arr.indexOf(2); // 最初の位置または -1

map / filter / reduce

함수형 순회: map으로 변환, filter로 거르고, reduce로 집계, find로 찾고, every/some로 판정. 새 배열을 반환하며 원본 배열은 바꾸지 않습니다.

1
2
3
4
5
6
7
8
9
const nums = [1, 2, 3, 4];
const doubled = nums.map(n => n * 2);
const evens = nums.filter(n => n % 2 === 0);
const sum = nums.reduce((acc, n) => acc + n, 0);
const found = nums.find(n => n > 2); // 3 | undefined
const ok = nums.every(n => n > 0); // true
const has = nums.some(n => n === 4); // true
// チェーン:
nums.filter(n => n % 2).map(n => n * 10).reduce((a, b) => a + b, 0);

객체 연산

스프레드로 합치기 {...a, ...b}, Object.keys/values/entries로 순회, keyof로 타입의 키.

1
2
3
4
5
6
7
8
9
10
const base = { id: 1, name: 'Nick' };
const extended = { ...base, age: 30 }; // マージ
const override = { ...base, name: 'New' }; // 上書き
const keys = Object.keys(base);
// 型安全な反復:
for (const key of Object.keys(base) as (keyof typeof base)[]) {
console.log(base[key]);
}
// entries:
for (const [k, v] of Object.entries(base)) { }

Map

Map은 임의 키 매핑: set/get/has/delete/size. 삽입 순서를 유지하고 O(1) 조회.

1
2
3
4
5
6
7
8
9
10
11
const scores = new Map<string, number>();
scores.set('alice', 90);
const v = scores.get('alice'); // number | undefined
scores.has('bob'); // false
scores.delete('alice');
scores.size;
// 反復:
for (const [k, val] of scores) { }
for (const key of scores.keys()) { }
// 初期化:
new Map([['a', 1], ['b', 2]]);

Set

Set은 중복 없는 집합: add/delete/has/size. 배열의 중복을 제거하거나 차집합/합집합을 구할 때 사용합니다.

1
2
3
4
5
6
7
8
9
10
const set = new Set<number>();
set.add(1).add(2).add(1); // {1, 2}
set.has(1); // true
set.delete(2);
// 配列の重複排除:
const unique = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]
// 和集合:
const union = new Set([...a, ...b]);
// 積集合:
const inter = new Set([...a].filter(x => bSet.has(x)));

불변 업데이트

제자리 변경 대신 스프레드/복사로 업데이트합니다. 객체 교체, 배열 추가/삭제는 새 참조를 반환합니다. React 상태에서 흔히 쓰입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface State {
items: string[];
count: number;
}
const next: State = {
...state,
items: [...state.items, 'new'], // 追加
count: state.count + 1,
};
// 1 件削除:
const filtered = state.items.filter(x => x !== 'old');
// 1 件更新:
const updated = state.items.map((x, i) => i === 0 ? 'new' : x);
// readonly で型チェックによる in-place 変更防止

튜플과 Record

튜플은 고정 길이, Record는 키-값 매핑입니다. 객체 리터럴에 as const를 붙여 상수로 변환합니다.

1
2
3
4
5
6
7
8
9
10
11
const point: [number, number] = [10, 20];
const [x, y] = point; // 分割代入
// Record:
type Config = Record<string, boolean>;
const flags: Config = { debug: true };
// as const 定数オブジェクト:
const statusMap = {
active: '运行中',
stopped: '已停止',
} as const;
// statusMap.active の型は '运行中' リテラル

WeakMap / WeakSet

WeakMap/WeakSet의 키는 반드시 객체여야 하며 약한 참조입니다. GC를 막지 않습니다. 메타데이터 캐싱이나 부작용용으로 사용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const meta = new WeakMap<object, { visited: boolean }>();
const node = document.getElementById('a');
if (node) meta.set(node, { visited: true });
// キーはオブジェクトのみ:
// meta.set(1, {}) // エラー
// 反復不可(keys/size なし)
// 用途:
// 1. オブジェクトにプライベートメタデータを紐付ける
// 2. 計算結果をキャッシュしてリークを防ぐ
// 3. リスナー用フラグ
// WeakSet は集合のマーキング用:
const processed = new WeakSet<object>();
processed.add(obj);
processed.has(obj); // true

9.성능과 메모리

가비지 컬렉션 아래의 메모리 관점, 대용량 데이터, 문자열 최적화와 모니터링.

가비지 컬렉션

TS/JS는 GC가 있어 수동 해제가 필요 없습니다. 더 이상 참조되지 않는 객체는 회수됩니다. 긴 수명을 가진 객체는 클로저가 붙잡고 있지 않도록 주의하세요.

1
2
3
4
5
6
7
8
9
10
// オブジェクトはスコープ外かつ参照なしで GC される
function create() {
const big = new Array(1e6);
return () => big.length; // クロージャが big を保持
}
// クロージャが big を生かしている:
const f = create(); // big は解放不可
// 解放:
f = null; // 参照を切る
// グローバルキャッシュが無限に膨らむのを避ける

대용량 배열

대용량 배열 연산에는 TypedArray나 스트리밍을 고려하세요. filter/map은 새 배열을 만들어 비용이 발생합니다. 반복문에서 재사용하는 편이 더 경제적입니다.

1
2
3
4
5
6
7
8
9
10
// TypedArray でバイナリ処理:
const buf = new Float64Array(1e6);
// 大きな配列で map/filter の連鎖を避ける:
// BAD:複数パス
// GOOD:1 パスで処理
const src = new Array(1e6).fill(0);
let sum = 0;
for (let i = 0; i < src.length; i++) sum += src[i];
// バイナリ:DataView + ArrayBuffer
// 数値精度:BigInt で大整数、BigInt.asIntN で切り詰め

문자열 메모리

문자열은 불변이며 이어 붙이면 새 문자열이 만들어집니다. 대량의 연결은 배열 join이나 템플릿을 사용하세요. 문자열 인터닝(interning).

1
2
3
4
5
6
7
8
9
// ループでの文字列連結は遅い:
let s = '';
for (let i = 0; i < 1e5; i++) s += i; // BAD
// 配列の join を使う:
const parts: string[] = [];
for (let i = 0; i < 1e5; i++) parts.push(String(i));
const s2 = parts.join(''); // GOOD
// またはテンプレート文字列で分割
// 長い文字列のスライスは slice(O(n))

WeakRef와 캐시

WeakRef는 약한 참조라 가비지 컬렉션을 막지 않고, WeakMap/WeakSet은 키가 약하게 참조됩니다. 캐시나 부작용 추적에 약한 컨테이너를 사용하세요.

1
2
3
4
5
6
7
8
9
const cache = new WeakMap<object, number>();
const obj = { id: 1 };
cache.set(obj, compute(obj));
// obj が GC されるとエントリも自動で消える
// WeakRef:
const ref = new WeakRef(obj);
const alive = ref.deref(); // object | undefined
// FinalizationRegistry で回収を監視:
const reg = new FinalizationRegistry(held => console.log('collected', held));

성능 팁

any 사용은 최적화를 늦추므로 피하고, 재할당을 줄이며, 결과를 캐시합니다. V8 최적화는 안정적인 형태의 객체에 의존합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 動的プロパティでオブジェクト形状を変えない:
// BAD:
const obj: Record<string, number> = {};
obj.a = 1; obj.b = 2; // 形状変化
// GOOD:完全な形状を宣言
const obj = { a: 0, b: 0 };
// 長いチェーンをキャッシュ:
const len = arr.length; // ループ内で再取得しない
// 暗黙の型変換を避ける:
const s = String(n) + x;
// ホットパスではクロージャ生成を避ける:
for (let i = 0; i < n; i++) { }
// map で毎回アロー関数を生成しない

메모리 모니터링

Node에서 메모리를 확인할 때는 process.memoryUsage(), --max-old-space-size를 사용합니다. 브라우저에서는 Performance API를 사용합니다.

1
2
3
4
5
6
7
8
9
// Node:
console.log(process.memoryUsage());
// heapUsed 使用済みヒープ、heapTotal 総ヒープ
// ヒープを増やす:node --max-old-space-size=4096 app.js
// ブラウザ:
performance.measureMemory?.()
.then(m => console.log(m.bytes));
// ヒープスナップショット:Chrome DevTools の Memory パネル
// リークの特徴:heapUsed が下がり続けることなく増加

클로저와 메모리

클로저는 외부 변수를 붙잡아 그 수명을 연장합니다. 반복문 안의 클로저 함정에 주의하세요. 참조를 해제합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function makeCounter() {
let count = 0; // クロージャにキャプチャされる
return () => ++count; // 生存する
}
const c = makeCounter();
c(); // 1
// ループ内クロージャキャプチャ(var の罠):
// BAD:var は共有される
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 3 3 3
}
// GOOD:let はブロックスコープでキャプチャ
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 0 1 2
}
// 長寿命クロージャの解放:
// fn = null

TypedArray와 바이너리

TypedArray는 바이너리 수치를 다룹니다: Uint8Array/Float64Array. 뷰는 내부 buffer를 공유합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const bytes = new Uint8Array(16); // 16 バイト
bytes[0] = 255;
// 既存データから作成:
const arr = new Uint8Array([1, 2, 3]);
// 浮動小数:
const floats = new Float64Array(8);
// バッファ共有:
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
view.setInt32(0, 42);
view.getInt32(0); // 42
// 通常の配列に変換:
const plain = Array.from(bytes);
// エンコード:
new TextEncoder().encode('中文');
// 大容量ファイル/ネットワークプロトコル/Canvas ピクセルで頻出

10.클래스와 객체 지향

class, 접근 제어자, 상속, 추상 클래스, 제네릭 클래스.

class 기본

class 문법: 필드, 생성자, 메서드. 필드는 타입과 가시성을 표기할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): string {
return `Hi, I'm ${this.name}`;
}
}
const p = new Person('Nick', 30);
// パラメータプロパティ shorthand:
class P2 {
constructor(public name: string, private age: number) {}
}

접근 제어자

public은 공개, private은 비공개, protected는 보호, readonly는 읽기 전용입니다. 모두 컴파일 시점에 검사됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
class Account {
public owner: string; // デフォルト public
private balance = 0; // プライベート
protected type = 'basic'; // サブクラスからアクセス可
readonly id: string; // 読み取り専用
constructor(owner: string) {
this.owner = owner;
this.id = crypto.randomUUID();
}
}
// # プライベートフィールド(実行時プライベート、ES2022):
class C { #secret = 1; get() { return this.#secret; } }

상속과 override

extends로 상속, super()로 부모 생성자 호출, override로 부모 메서드 재정의. 자식은 부모의 일종입니다(is-a).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal {
constructor(public name: string) {}
speak(): string { return `${this.name} makes a sound`; }
}
class Dog extends Animal {
constructor(name: string, public breed: string) {
super(name); // まず親コンストラクタを呼ぶ
}
override speak(): string { // override を明示
return `${this.name} barks`;
}
}
const d = new Dog('Rex', 'Husky');
// d は Dog であり Animal でもある

추상 클래스와 인터페이스

abstract 클래스는 인스턴스화할 수 없으며, 추상 메서드는 자식이 반드시 구현해야 합니다. 인터페이스는 모양을 제약합니다. 추상 클래스는 구현을 가질 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class Shape {
abstract area(): number; // サブクラスは必ず実装
describe(): string {
return `Area: ${this.area()}`;
}
}
class Circle extends Shape {
constructor(private r: number) { super(); }
override area(): number { return Math.PI * this.r ** 2; }
}
// interface 制約:
interface HasArea { area(): number }
function printArea(s: HasArea) { console.log(s.area()); }

implements

class implements 인터페이스: 클래스는 인터페이스의 모양을 충족해야 합니다. 한 클래스가 여러 인터페이스를 구현할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
interface Runnable {
run(): void;
}
interface Jumpable {
jump(): void;
}
class Player implements Runnable, Jumpable {
run(): void { console.log('running'); }
jump(): void { console.log('jump'); }
}
// メソッド不足はコンパイルエラー
// implements は形の制約のみ、継承関係を要求しない

제네릭 클래스

제네릭 클래스: 타입 매개변수는 필드와 메서드에 사용된다. 제약을 통해 제네릭의 범위를 한정한다.

1
2
3
4
5
6
7
8
9
10
11
class Box<T> {
private value: T;
constructor(value: T) { this.value = value; }
get(): T { return this.value; }
set(v: T): void { this.value = v; }
}
const numBox = new Box<number>(42);
const strBox = new Box('hi'); // string と推論
// 静的メンバーは型パラメータを参照できない:
// static arr: T[] // エラー
// ジェネリック制約:class Box<T extends { id: number }>

getter / setter

get/set 접근자가 필드의 읽기/쓰기를 감싼다. 검증과 계산 로직을 추가할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Temperature {
private _celsius = 0;
get celsius(): number { return this._celsius; }
set celsius(value: number) {
if (value < -273.15) throw new Error('绝对零度以下');
this._celsius = value;
}
get fahrenheit(): number {
return this._celsius * 9 / 5 + 32;
}
}
const t = new Temperature();
t.celsius = 25;
console.log(t.fahrenheit); // 77

정적 멤버

static은 클래스 수준의 필드와 메서드를 정의한다. 정적 멤버는 인스턴스에 의존하지 않는다. 팩토리 메서드와 상수에 static을 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MathHelper {
static readonly PI = 3.14159; // クラス定数
static max(arr: number[]): number {
return Math.max(...arr);
}
// ファクトリーメソッド:
static create(name: string): MathHelper {
return new MathHelper(name);
}
constructor(private name: string) {}
}
MathHelper.PI;
MathHelper.max([1, 5, 3]);
// 静的メンバーはクラス名でアクセス:
// new MathHelper().PI // エラー
// 静的プロパティ初期化はクラス定義時に実行される

11.예외 처리

throw/try-catch, 오류 타입, 사용자 정의 오류, 비동기 오류.

throw / try-catch

throw로 오류를 던지고, try-catch로 잡고, finally로 마무리한다. catch 변수는 기본적으로 unknown이므로 좁혀야 한다.

1
2
3
4
5
6
7
8
9
10
11
try {
const n = JSON.parse(text);
if (typeof n !== 'number') throw new Error('需要数字');
} catch (err) {
if (err instanceof Error) {
console.log(err.message); // 絞り込み後にアクセス
}
} finally {
cleanup(); // 成否に関わらず実行
}
// キャッチしないと上位へ伝播、未処理だとクラッシュ

사용자 정의 오류

extends Error로 사용자 정의 오류 클래스를 만든다. 추가 정보를 함께 담는다. 오류 이름은 타입을 구분하는 데 쓰인다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ValidationError extends Error {
constructor(public field: string, message: string) {
super(message);
this.name = 'ValidationError';
}
}
try {
throw new ValidationError('email', '邮箱格式错误');
} catch (err) {
if (err instanceof ValidationError) {
console.log(err.field, err.message);
}
}
// プロトタイプチェーンを確実に(instanceof のため):
// Object.setPrototypeOf(this, ValidationError.prototype)

일반적인 오류 타입

Error 베이스 클래스: TypeError 타입 오류, RangeError 범위 초과, ReferenceError 참조 오류. 판별은 instanceof를 쓴다.

1
2
3
4
5
6
7
8
9
10
11
12
try {
// TypeError: 存在しないメソッド呼び出し
// RangeError: 配列範囲外 / 再帰が深すぎる
// ReferenceError: 未宣言変数の参照
const arr = [1, 2];
arr[5].toFixed(); // TypeError
} catch (err) {
if (err instanceof TypeError) { }
else if (err instanceof RangeError) { }
// instanceof Error でフォールバック
}
// クロス realm では name 属性で判定

비동기 오류

async 함수의 throw는 rejected Promise가 된다. await 시 try-catch로 잡는다. Promise.catch 체이닝.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function load(): Promise<void> {
try {
const res = await fetch('/api');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
} catch (err) {
console.error('加载失败', err);
}
}
// Promise チェーン:
fetch('/api').then(r => r.json()).catch(e => {
console.error(e);
});
// 未処理の rejected Promise は unhandledrejection をトリガ

오류 경계

모듈 경계에서 오류를 잡아 변환한다. 서드파티 오류는 통일해 감싼다. 오류가 빠져나가면 크래시가 발생한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function safeParse<T>(json: string): T {
try {
return JSON.parse(json) as T;
} catch {
throw new Error('JSON 解析失败'); // 統一的にラップ
}
}
// エントリでキャッチ:
process.on('uncaughtException', (err) => {
console.error('未捕获异常', err);
process.exit(1);
});
// Node では同期例外をトップレベルでフォールバック
// ブラウザ:window.onerror / unhandledrejection

오류 처리 패턴

예측 가능한 오류는 결과로 반환하고, 예상치 못한 오류는 예외를 던진다. Result 스타일(ok/err)과 throw는 각각의 쓰임이 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 予想可能な失敗:null / Result オブジェクトを返す
type Result<T> = { ok: true; value: T } | { ok: false; error: string };
function parseNum(s: string): Result<number> {
const n = Number(s);
return Number.isNaN(n)
? { ok: false, error: '不是数字' }
: { ok: true, value: n };
}
const r = parseNum('abc');
if (r.ok) console.log(r.value);
else console.log(r.error);
// 予想外の失敗:throw + 上位でキャッチ
// ルール:呼び出し側が処理できるなら返す、そうでなければ throw
// 握り潰さない:catch 後は少なくとも log

오류 메시지 품질

오류 메시지에는 맥락이 포함된다: 무엇이, 어디서, 어떻게 고치는지. 사용자 정의 오류는 필드를 함께 담는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class HttpError extends Error {
constructor(
public status: number,
public url: string,
message: string,
) {
super(message);
this.name = 'HttpError';
}
}
// GOOD:コンテキスト付き
throw new HttpError(404, url, `资源不存在: ${url}`);
// BAD:情報不足
// throw new Error('失败了');
// ログにスタックを含める:
console.error(err); // stack を保持
// エラー原因チェーン:
new Error('外层失败', { cause: innerErr })

처리되지 않은 거부

잡히지 않은 rejected Promise는 unhandledrejection을 발생시킨다. 최상위에서 안전망을 둬 조용한 실패를 방지한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Node:
process.on('unhandledRejection', (reason) => {
console.error('未处理的 Promise 拒绝', reason);
});
// ブラウザ:
window.addEventListener('unhandledrejection', (e) => {
e.preventDefault();
console.error('未处理拒绝', e.reason);
});
// 同期例外:
process.on('uncaughtException', (err) => {
console.error('未捕获异常', err);
process.exit(1);
});
// 監査:テストでリスナーを張って取りこぼし検知
// フォールバックは握り潰しではなく、ログと特定

12.입출력

console 출력, Node 파일/스트림, fetch 네트워크, 타입이 지정된 JSON.

console 출력

console.log/info/warn/error, 템플릿 출력, %o 포맷, 그룹과 카운트.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
console.log('Hello');
console.info('info 消息');
console.warn('警告');
console.error('错误');
// フォーマット:
console.log('%o', { a: 1 }); // オブジェクト展開
console.table([{ a: 1 }, { a: 2 }]);
// グループ:
console.group('组');
console.log('内容');
console.groupEnd();
// 時間計測:
console.time('t');
console.timeEnd('t');

fetch 네트워크

fetch는 비동기 요청이다. 응답을 await하고, json을 파싱하며, 오류를 처리하고, 결과를 타입 단언한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
async function getUsers(): Promise<User[]> {
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json() as Promise<User[]>; // アサーション
}
// POST:
await fetch('/api', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Nick' }),
});
// AbortController でタイムアウト:
const ac = new AbortController();
setTimeout(() => ac.abort(), 3000);
await fetch(url, { signal: ac.signal });

Node 파일

fs/promises로 비동기 읽기/쓰기. readFile/writeFile/mkdir/readdir은 Promise를 반환한다.

1
2
3
4
5
6
7
8
9
10
import { readFile, writeFile, mkdir, readdir } from 'node:fs/promises';
const text = await readFile('data.txt', 'utf8');
await writeFile('out.txt', text.toUpperCase());
await mkdir('dir', { recursive: true });
const files = await readdir('.');
// 大容量ファイルのストリーム:
import { createReadStream } from 'node:fs';
const stream = createReadStream('big.log');
// @types/node が必要:
// npm i -D @types/node

JSON과 타입

JSON.parse/stringify 직렬화. parse 결과는 가드로 검증이 필요하고, stringify는 함수를 무시한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
interface User { name: string; age: number }
const u: User = { name: 'Nick', age: 30 };
const json = JSON.stringify(u);
// パース後にバリデーション:
function isUser(v: unknown): v is User {
return typeof v === 'object' && v !== null
&& typeof (v as any).name === 'string'
&& typeof (v as any).age === 'number';
}
const data = JSON.parse(json);
if (isUser(data)) console.log(data.name);
// JSON.parse は any を返すためアサート前にガード推奨
// シリアライズオプション:JSON.stringify(u, null, 2) で整形

스트리밍 처리

ReadableStream/Web Streams로 대용량 응답을 처리한다. 진행 상황을 읽고, 청크 단위로 처리한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const res = await fetch('/big');
const reader = res.body!.getReader();
const decoder = new TextDecoder();
let total = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
total += value.length;
const chunk = decoder.decode(value, { stream: true });
process(chunk);
}
// 大容量ファイルをストリーム読み込み:
// for await (const chunk of createReadStream('big.log')) { }

환경 변수와 인자

Node에서 process.argv / process.env를 읽는다. 인자 파싱, 환경 변수 타입 좁히기.

1
2
3
4
5
6
7
8
9
10
11
// process.argv[0]=node, [1]=スクリプト, [2..] 引数
const args = process.argv.slice(2);
// 環境変数:
const port = Number(process.env.PORT ?? 3000);
const mode = process.env.NODE_ENV ?? 'development';
// 判定:
if (mode === 'production') { }
// .env 読み込み:
// npm i dotenv
// import 'dotenv/config'
// 型安全な環境:process.env は Record<string, string | undefined>

브라우저 Web API

localStorage/sessionStorage, navigator, WebSocket의 타입. 저장 값은 직렬화가 필요하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ローカルストレージ:
localStorage.setItem('token', 'abc');
const t = localStorage.getItem('token'); // string | null
// オブジェクト保存にはシリアライズが必要:
localStorage.setItem('user', JSON.stringify(user));
// 読み戻しはパース + 検証:
const raw = localStorage.getItem('user');
if (raw) { const u = JSON.parse(raw) as User; }
// ナビゲーション:
if ('geolocation' in navigator) {
navigator.geolocation.getCurrentPosition((pos) => {
console.log(pos.coords.latitude);
});
}
// WebSocket イベント型:
ws.addEventListener('message', (e: MessageEvent) => {
console.log(e.data);
});

파일 읽기

input[type=file]로 File을 얻고, FileReader로 텍스트/DataURL을 읽으며, 객체 URL로 미리 본다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const input = document.querySelector('input[type=file]') as HTMLInputElement;
input.addEventListener('change', async () => {
const file = input.files?.[0];
if (!file) return;
// テキスト読み込み:
const text = await file.text();
// DataURL として読み込み:
const reader = new FileReader();
reader.onload = () => console.log(reader.result);
reader.readAsDataURL(file);
// 画像プレビュー:
const url = URL.createObjectURL(file);
img.src = url;
// File には name/size/type がある
console.log(file.name, file.size, file.type);
});

13.흔한 실수

일상 개발에서 가장 자주 겪는 함정과 올바른 작성법.

any 남용

any는 타입 검사를 꺼 실제 오류를 가린다. unknown + 가드가 가능하면 그쪽을 쓴다.

1
2
3
4
5
6
7
8
9
10
// BAD:any がエラーを握り潰す
function getLen(v: any): number {
return v.length; // コンパイル通過、ランタイムでクラッシュの可能性
}
// GOOD:unknown + ガード
function getLen(v: unknown): number {
if (typeof v !== 'string') return 0;
return v.length;
}
// any の暗黙伝播:戻り値 any が呼び出し側を汚染

빈 값 판별

!!로 truthy 판별, == null로 null/undefined 동시 판별, 배열의 빈 판별. 0이나 ''를 빈 값으로 취급하지 않는다.

1
2
3
4
5
6
7
8
9
10
// BAD:値が 0 や '' の可能性あり
if (value) { } // 0 は falsy
// GOOD:明示的に null を判定
if (value !== null && value !== undefined) { }
// 簡略 == null で両方判定:
if (value == null) { } // null または undefined
// 配列が空の判定:
if (arr.length === 0) { }
// オブジェクトが空の判定:
if (Object.keys(obj).length === 0) { }

async 오용

async 함수는 반드시 Promise를 반환한다. await를 잊으면 Promise가 누출된다. forEach는 async 대기를 지원하지 않는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// BAD:forEach は待たない
async function main() {
[1, 2, 3].forEach(async n => { await work(n); });
console.log('done'); // 先に表示される!
}
// GOOD:for...of
for (const n of [1, 2, 3]) {
await work(n);
}
// BAD:await を忘れる
const res = fetch('/api'); // Promise のまま
// 並列:
await Promise.all([a(), b()]);

동등 비교

===는 엄격한 동등이다. NaN !== NaN. 객체는 참조로 비교한다. 깊은 비교는 직접 작성하거나 라이브러리를 쓴다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// BAD:== の緩い比較は型変換される
'1' == 1; // true、落とし穴
// GOOD:=== で厳密比較
'1' === 1; // false
// NaN は特殊:
NaN === NaN; // false
Number.isNaN(NaN); // true
// オブジェクトは参照で比較:
{} === {}; // false
// 配列内容の比較:
[1, 2].join() === [1, 2].join(); // 簡易版
// 深い比較ライブラリ:
// import { isEqual } from 'lodash-es';
// パフォーマンス:深いオブジェクトの頻繁な比較を避ける

null과 undefined 혼동

null은 의도적인 빈 값이고, undefined는 미할당이다. strictNullChecks에서 따로 처리한다. 옵셔널 체이닝 대 단언.

1
2
3
4
5
6
7
8
9
10
11
12
// BAD:アサーションが null を見えなくする
const len = name!.length; // name が実際に null かもしれない
// GOOD:先に判定
if (name) {
const len = name.length;
}
// null 合体:
const n = name ?? 'default';
// オプショナルチェーンで安全アクセス:
user?.profile?.email;
// ?? を使う(|| ではなく):0 や '' は有効値
const port = port ?? 3000; // port=0 のとき 0 を保持

this 손실

콜백에서 this는 undefined가 된다. 화살표 함수로 바인딩하거나 명시적으로 바인딩한다. 클래스 필드에서 화살표 함수가 자주 쓰인다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Counter {
count = 0;
increment = () => { this.count++; }; // アローで束縛
}
// BAD:コールバックで this が失われる
class C {
value = 1;
method() { return this.value; }
}
const fn = new C().method;
fn(); // undefined エラー
// GOOD:
const fn2 = new C().method.bind(new C());
// または呼び出し時に .method() 形式で

좁히기 실패

속성에 접근한 후에는 좁히기가 사라진다. 분해할당 후에야 좁혀진다. 함수 매개변수를 재할당하면 타입이 넓어진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// BAD:プロパティの絞り込みが保たれない
function f(p: { a?: string }) {
if (p.a) {
p.a.toUpperCase(); // 既に変化している可能性
}
}
// GOOD:一旦変数に保存
function f2(p: { a?: string }) {
const a = p.a;
if (a) {
a.toUpperCase();
}
}
// オプショナルプロパティを 2 回参照すると競合の可能性
// 引数を再代入すると絞り込みが失われる:
// let x = v; その後判定

완전 검사

구별 가능한 유니온의 default에서 never로 검사한다. 새 타입 분기를 누락하면 컴파일 오류가 난다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// GOOD:default で never を使い網羅性チェック
type Event =
| { kind: 'open' }
| { kind: 'close' };
function handle(e: Event) {
switch (e.kind) {
case 'open': break;
case 'close': break;
default: {
const _exhaustive: never = e;
// 新しい kind 追加時ここでコンパイルエラー
return _exhaustive;
}
}
}
// BAD:default を付けない、新規型は黙って未処理
// 型を更新するとコンパイラが全 switch をチェック

복사와 변경

배열/객체 참조 공유로 잘못 변경될 수 있다. 업데이트할 때는 복사한다. sort는 배열을 제자리에서 바꾼다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const a = [1, 2, 3];
// BAD:sort は in-place
const sorted = a.sort(); // a も変わる
// GOOD:先にコピー
const sorted = [...a].sort();
// BAD:参照共有による誤変更
const b = a;
b.push(4); // a も変わる
// シャローコピー:
const copy = [...a];
// オブジェクトスプレッドでシャローコピー:
const o2 = { ...o1 };
// ネストした深いコピーは層ごとに処理が必要

14.동시성과 비동기

Promise, async/await, Worker 스레드와 이벤트 루프.

Promise

Promise는 비동기 결과를 나타낸다. then 체이닝, catch 오류, finally 마무리. 타입은 Promise<T>로 표기한다.

1
2
3
4
5
6
7
8
9
10
const p: Promise<number> = new Promise((resolve, reject) => {
setTimeout(() => resolve(42), 1000);
});
p.then(n => console.log(n))
.catch(err => console.error(err))
.finally(() => console.log('done'));
// 即時作成:
Promise.resolve(1);
Promise.reject(new Error('x'));
// ジェネリクス:Promise<T> の成功値型は T

async / await

async 함수는 Promise를 반환한다. await가 풀어준다. 오류는 try-catch로 다룬다. 최상위 await에는 ESM이 필요하다.

1
2
3
4
5
6
7
8
9
10
11
12
async function load(): Promise<User> {
const res = await fetch('/api/user');
if (!res.ok) throw new Error('加载失败');
return res.json() as Promise<User>;
}
// 呼び出し:
const user = await load();
// エラー:
try { await load(); } catch (err) { }
// 並列実行:
const [a, b] = await Promise.all([load(), load()]);
// トップレベル await(ESM .mjs)

병렬과 경합

Promise.all은 전부 완료, allSettled은 전부(실패 포함), race는 가장 먼저 완료, any는 첫 성공.

1
2
3
4
5
6
7
8
9
10
11
const tasks = [fetch1(), fetch2(), fetch3()];
// 全部成功(1 つでも失敗で全体失敗):
const all = await Promise.all(tasks);
// 中断せず全結果を収集:
const settled = await Promise.allSettled(tasks);
// 最初に完了したもの(失敗含む):
const first = await Promise.race(tasks);
// 最初に成功したもの(全部失敗で AggregateError):
const any = await Promise.any(tasks);
// 並列数制限:
// for ループで分割、または p-limit ライブラリ

Worker 스레드

Web Worker / Node worker_threads로 병렬 계산. postMessage 통신, transferable로 소유권을 이전한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// メインスレッド:
const worker = new Worker('/worker.js');
worker.postMessage({ n: 42 });
worker.onmessage = (e) => console.log(e.data);
worker.onerror = (e) => console.error(e);
// worker.js:
self.onmessage = (e) => {
const result = heavyCompute(e.data.n);
self.postMessage(result);
};
// Node:
// import { Worker } from 'node:worker_threads';
// 大きなオブジェクトは transfer:
// postMessage(buf, [buf.buffer])

이벤트 루프

동기 코드가 먼저 실행되고, 마이크로태스크(Promise)가 매크로태스크(setTimeout)보다 먼저다. 블로킹은 모든 것을 멈추게 한다.

1
2
3
4
5
6
7
8
9
console.log('1'); // 同期
Promise.resolve().then(() =>
console.log('2')); // マイクロタスク
setTimeout(() => console.log('3'), 0); // マクロタスク
console.log('4');
// 出力順:1 4 2 3
// 長時間タスクがイベントループをブロック:
// for (let i=0;i<1e9;i++){} // 固まる
// 分割または譲歩:await new Promise(r => setTimeout(r, 0))

제너레이터

function* 제너레이터는 지연 생성한다. yield로 일시정지/재개. Generator 타입 표기.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function* count(max: number): Generator<number> {
let i = 0;
while (i < max) {
yield i++; // 一時停止して値を返す
}
}
for (const n of count(3)) console.log(n); // 0 1 2
// 手動で進める:
const g = count(2);
g.next(); // { value: 0, done: false }
g.next();
// 無限シーケンス + 遅延評価:
function* naturals(): Generator<number> {
let n = 0;
while (true) yield n++;
}
// イテレータプロトコルと等価

비동기 이터레이터

for await로 비동기 데이터 소스를 순회한다. 비동기 제너레이터는 async function*. 스트림 데이터를 소비한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
async function* generate(): AsyncGenerator<number> {
let i = 0;
while (i < 3) {
await new Promise(r => setTimeout(r, 100));
yield i++;
}
}
// 消費:
for await (const n of generate()) {
console.log(n); // 0 1 2
}
// 非同期イテラブルの利用例:
const res = await fetch('/big');
const reader = res.body!.getReader();
// Node ストリーム:
// for await (const chunk of createReadStream('f'))
// 遅延 + バックプレッシャー、メモリに優しい

동시성 제한

동시에 실행되는 비동기 작업 수를 제어한다. 배치, 세마포어 또는 p-limit 방식. 자원 과부하를 피한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
async function mapLimit<T, R>(
items: T[], limit: number, fn: (x: T) => Promise<R>,
): Promise<R[]> {
const results: R[] = [];
let i = 0;
const workers = Array.from({ length: Math.min(limit, items.length) },
async () => {
while (i < items.length) {
const idx = i++;
results[idx] = await fn(items[idx]);
}
});
await Promise.all(workers);
return results;
}
// 用途:分割ダウンロード/リクエスト、limit で並列度を制御
// 一括送信を避けたいバッチ処理など

15.네트워크와 모듈

모듈 시스템, import/export, fetch와 타입이 지정된 API 캡슐화.

ES 모듈

import/export 정적 가져오기/내보내기. TS 타입 내보내기는 export type을 쓴다. 모듈은 스코프를 격리한다.

1
2
3
4
5
6
7
8
9
10
11
// utils.ts:
export const version = '1.0';
export function add(a: number, b: number): number { return a + b; }
export type ID = string; // 型のエクスポート
export default class App { } // デフォルトエクスポート
// main.ts:
import App, { add, version, type ID } from './utils';
// リネーム:
import { add as plus } from './utils';
// 全体インポート:
import * as utils from './utils';

타입 가져오기

import type은 타입만 가져오며 컴파일 시 지워진다. 런타임 의존과 순환 참조를 피한다.

1
2
3
4
5
6
7
8
9
10
11
// BAD:型がランタイムに残る(esbuild で残ることがある)
// GOOD:
import type { User } from './types';
// ミックス:
import { fetchUsers, type User } from './api';
// 型のみ:
import type { Options } from './config';
// 型のエクスポート:
export type { ID } from './utils';
// コンパイラが自動で elide、明示するとより明確
// 循環参照時は import type で断ち切る

타입이 지정된 API 캡슐화

fetch를 캡슐화해 강한 타입을 반환한다. 응답 검증, 오류를 통일해 처리. 제네릭 요청 함수.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
async function api<T>(
url: string, opts?: RequestInit
): Promise<T> {
const res = await fetch(url, opts);
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
return res.json() as Promise<T>;
}
// 使用例:
interface User { name: string }
const user = await api<User>('/api/user');
// ジェネリクスで呼び出し側が型安全に
// 境界では schema バリデーション(zod)で実行時のズレを防ぐ
// import { z } from 'zod';

Node HTTP 서비스

node:http 또는 프레임워크(Express/Fastify). 타입화된 요청 응답. 라우팅 처리.

1
2
3
4
5
6
7
8
9
10
11
import { createServer } from 'node:http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true }));
});
server.listen(3000);
// Express:
// import express from 'express';
// @types/express が型を提供
// パラメータの型:
// app.get('/user/:id', (req: Request<{id: string}>, res: Response) => {})

DOM 타입

document.getElementById 반환 타입, 이벤트 타입, HTML 요소 타입 매핑.

1
2
3
4
5
6
7
8
9
10
const btn = document.getElementById('btn');
// HTMLElement | null、非 null チェックが必要:
if (btn) { btn.addEventListener('click', handler); }
// 具体要素にアサート:
const input = document.querySelector('input') as HTMLInputElement;
// イベント型:
function handler(e: MouseEvent) { console.log(e.clientX); }
// ジェネリックイベント:
const f = (e: KeyboardEvent) => { e.key };
// フォームの値取得:input.value は string

URL과 매개변수

URLSearchParams로 쿼리 문자열 구성, URL 파싱. 타입 안전 매개변수 읽기.

1
2
3
4
5
6
7
8
9
const params = new URLSearchParams({ q: 'ts', page: '2' });
params.toString(); // 'q=ts&page=2'
const url = new URL('https://example.com/search?q=ts');
const q = url.searchParams.get('q'); // 'ts'
// 組み立て:
url.searchParams.set('page', '3');
// リクエストヘッダ:
headers.append('Authorization', `Bearer ${token}`);
// パラメータ型:get は string | null を返すため絞り込んで使う

WebSocket

WebSocket 양방향 통신. onmessage 이벤트, 제네릭 데이터, readyState 상태.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const ws = new WebSocket('wss://example.com/socket');
// 接続確立:
ws.onopen = () => ws.send(JSON.stringify({ type: 'join' }));
// 受信:
ws.onmessage = (e: MessageEvent) => {
// e.data は string | Blob | ArrayBuffer の可能性
const data = JSON.parse(e.data as string);
console.log(data);
};
ws.onerror = (e) => console.error('连接错误', e);
ws.onclose = (e) => console.log('关闭', e.code);
// 能動的に閉じる:
ws.close(1000, '正常关闭');
// 自動再接続:onclose 内で setTimeout 再接続

요청 헤더와 인증

Headers 타입 안전 설정. Authorization Bearer, Content-Type. 인터셉터로 일괄 주입.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const headers = new Headers();
headers.set('Content-Type', 'application/json');
headers.set('Authorization', `Bearer ${token}`);
const res = await fetch('/api', { headers });
// レスポンスヘッダ読み取り:
const type = res.headers.get('content-type');
// 共通化ラッパー:
function authFetch(url: string, init?: RequestInit) {
return fetch(url, {
...init,
headers: {
...init?.headers,
Authorization: `Bearer ${getToken()}`,
},
});
}
// 注意:token 漏洩防止のためログ/URL に含めない
// リフレッシュ:401 時に token を更新して再試行

16.시간과 날짜

Date 객체, 타임스탬프, 서식 지정과 시간대.

Date 기초

Date 생성, getFullYear/getMonth/getDate 읽기, set 계열 설정. 월은 0부터 시작.

1
2
3
4
5
6
7
8
9
10
11
const now = new Date();
const d = new Date('2026-08-02T12:00:00Z');
const y = d.getFullYear(); // 2026
const m = d.getMonth(); // 7(0 から!)
const day = d.getDate(); // 2
// 設定:
d.setFullYear(2030);
d.setMonth(0); // 1 月
// ローカルと UTC:
// getUTCFullYear() / getUTCHours()
// getTimezoneOffset() 分差

타임스탬프

getTime() 밀리초 타임스탬프, Date.now(), Date.parse. 날짜 비교는 타임스탬프 사용.

1
2
3
4
5
6
7
8
9
const ms = Date.now(); // 現在のミリ秒
const d = new Date(ms);
const older = new Date('2020-01-01');
if (d.getTime() > older.getTime()) { } // 比較
// 秒単位:Math.floor(Date.now() / 1000)
// Date.parse('2026-08-02') はミリ秒を返す
// 日時の加算:
d.setDate(d.getDate() + 7); // 7 日加算
// setMonth/setDate は月跨ぎを自動処理

서식 지정

toISOString UTC 형식, toLocaleDateString 로컬 형식, Intl.DateTimeFormat 사용자 정의.

1
2
3
4
5
6
7
8
9
10
const d = new Date();
const iso = d.toISOString(); // '2026-08-02T04:00:00.000Z'
const local = d.toLocaleDateString('zh-CN');
// Intl でカスタム:
new Intl.DateTimeFormat('zh-CN', {
year: 'numeric', month: 'long', day: 'numeric',
hour: '2-digit', minute: '2-digit',
}).format(d);
// 相対時間:
// d.toLocaleTimeString('zh-CN')

시간대

타임스탬프는 UTC 밀리초이며, 서식 지정 시에만 로컬 시간대가 적용됨. Intl은 timeZone 옵션으로 시간대를 지정함.

1
2
3
4
5
6
7
8
9
10
11
const d = new Date();
// タイムゾーン指定:
new Intl.DateTimeFormat('zh-CN', {
timeZone: 'Asia/Shanghai',
hour12: false,
}).format(d);
// getTimezoneOffset はローカルと UTC の分差を返す
// 保存は ISO/タイムスタンプ、表示はローカライズ
// タイムゾーン跨ぎ変換:
// UTC で保存、読み出し時に toLocaleString('zh-CN', { timeZone })
// 単純計算は dayjs/date-fns ライブラリ

타이머

setTimeout 지연, setInterval 주기, clearTimeout 취소. 반환 타입은 number.

1
2
3
4
5
6
7
8
9
10
11
const timer = setTimeout(() => {
console.log('1s 后');
}, 1000);
clearTimeout(timer); // キャンセル
const interval = setInterval(() => {
console.log('每秒');
}, 1000);
clearInterval(interval); // 停止
// 非同期待機:
await new Promise(r => setTimeout(r, 500));
// 注意:タイマーコールバックはイベントループのマクロタスクで実行される

기간과 구간

두 타임스탬프의 차는 밀리초 기간. 구간 판단은 타임스탬프 비교 사용. setInterval 드리프트 남용 방지.

1
2
3
4
5
6
7
8
9
10
11
const start = Date.now();
// 経過時間計測:
const elapsed = Date.now() - start; // ミリ秒
console.log(`${elapsed}ms`);
// 区間判定:
const inWindow = t >= start && t <= end;
// N ミリ秒ごと(ポーリング):
const poll = setInterval(() => { }, 1000);
// setInterval のドリフト補正:
// setTimeout 再帰 + 補正計算
// 精度:performance.now() の方が高い

날짜 라이브러리

dayjs/date-fns는 명확한 API와 시간대 처리를 제공함. 용량이 작고 불변임. 복잡한 시간대는 라이브러리 사용 권장.

1
2
3
4
5
6
7
8
9
10
11
12
13
// dayjs:
// import dayjs from 'dayjs';
// dayjs().format('YYYY-MM-DD');
// dayjs().add(7, 'day').toDate();
// dayjs('2026-08-02').isBefore('2026-09-01');
// date-fns:
// import { format, addDays, isBefore } from 'date-fns';
// format(new Date(), 'yyyy-MM-dd');
// addDays(new Date(), 7);
// タイムゾーン:
// import { formatInTimeZone } from 'date-fns-tz';
// formatInTimeZone(d, 'Asia/Shanghai', 'yyyy-MM-dd HH:mm')
// いずれもイミュータブル:新しい値を返し元の Date は変更しない

고정밀 타이밍

performance.now()는 시스템 시간 조정의 영향을 받지 않는 밀리초 단위 고정밀 시간. 성능 측정용.

1
2
3
4
5
6
7
8
9
10
11
12
13
const t0 = performance.now();
// コードを計測…
const elapsed = performance.now() - t0;
console.log(`${elapsed.toFixed(2)}ms`);
// 壁時計時間:Date.now() は変更され得る
// performance.now() は単調増加
// ブラウザ/Node 両方で利用可能
// マーカー分析:
performance.mark('start');
// …
performance.mark('end');
performance.measure('任务', 'start', 'end');
// 計測結果:performance.getEntriesByName('タスク')

17.프로세스와 시스템

Node 프로세스, 명령행 도구, 표준 스트림과 빌드 산출물 실행.

Node 프로세스

process 전역 객체: argv 매개변수, env 환경, exit 종료 코드, stdout/stderr 스트림.

1
2
3
4
5
6
7
8
9
10
import { argv, env, exit, stdout, stderr } from 'node:process';
const args = argv.slice(2);
const mode = env.NODE_ENV;
exit(0); // 正常終了
stdout.write('输出');
stderr.write('错误');
// 終了コード:0 成功、1 一般エラー
process.exitCode = 1; // 優雅に設定
// シグナル処理:
process.on('SIGINT', () => { console.log('Ctrl+C'); process.exit(0); });

명령행 도구

CLI 작성: 매개변수 파싱, 도움말 출력, 종료 코드. shebang으로 스크립트 실행 가능하게 함.

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env node
const [cmd, ...rest] = process.argv.slice(2);
if (cmd === '--help' || cmd === '-h') {
console.log('用法: ts-tool <命令> [选项]');
process.exit(0);
}
if (!cmd) {
console.error('缺少命令');
process.exit(1);
}
// 引数パースライブラリ:commander / yargs
// オプション:
// ts-tool build --out dist --watch

표준 스트림

stdin으로 입력 읽기, stdout으로 출력, stderr로 오류. readline 상호작용. 파이프 데이터.

1
2
3
4
5
6
7
8
9
10
11
import { stdin, stdout } from 'node:process';
import * as readline from 'node:readline/promises';
const rl = readline.createInterface({ input: stdin, output: stdout });
const name = await rl.question('名字? ');
console.log(`你好, ${name}`);
rl.close();
// 全 stdin を読み込み:
import { readFileSync } from 'node:fs';
// パイプ:echo hi | ts-tool
// 行ごと処理:
for await (const line of rl) { process(line); }

컴파일 산출물 실행

tsc 컴파일 후 node dist/main.js로 실행. package.json bin으로 명령 등록. 타입 선언 d.ts.

1
2
3
4
5
6
7
8
9
10
11
// package.json:
// {
// "bin": { "ts-tool": "./dist/cli.js" },
// "types": "./dist/index.d.ts",
// "main": "./dist/index.js"
// }
// コンパイル:npx tsc
// 実行:node dist/cli.js
// npm 公開:npm publish
// 宣言ファイル .d.ts を他 TS プロジェクトが参照可能
// tsconfig declaration: true

시스템 명령 실행

execFile로 외부 명령 실행, spawn은 스트리밍. child_process 타입. 인젝션 방지를 위한 이스케이프 주의.

1
2
3
4
5
6
7
8
9
10
11
import { execFile } from 'node:child_process';
execFile('ls', ['-l'], (err, stdout) => {
if (err) { console.error(err); return; }
console.log(stdout);
});
// ストリーミング spawn:
import { spawn } from 'node:child_process';
const child = spawn('node', ['worker.js']);
child.stdout.on('data', (d) => console.log(d.toString()));
// セキュリティ:exec + 文字列連結は避ける
// 引数は配列で渡し、シェルコマンドを連結しない

종료 코드

0은 성공, 0이 아니면 실패. 관례: 1은 일반 오류, 2는 사용법 오류. 스크립트는 CI에서 종료 코드에 의존함.

1
2
3
4
5
6
7
8
9
process.exit(0); // 成功
process.exit(1); // 一般エラー
process.exit(2); // 使用法/引数エラー
// 未捕捉例外は終了コード 1
// 手動設定:
process.exitCode = 2;
// CI で終了コードが 0 以外は失敗:
// ts-tool check && echo OK || echo FAIL
// シグナル終了:SIGTERM はデフォルト 143

npm scripts

package.json scripts로 명령 오케스트레이션. pre/post 훅, && 직렬, & 병렬. 빌드 체인에서 자주 사용.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// package.json:
// {
// "scripts": {
// "dev": "tsx src/dev.ts",
// "typecheck": "tsc --noEmit",
// "lint": "eslint src",
// "test": "vitest run",
// "build": "npm run typecheck && tsup src/index.ts",
// "prepublishOnly": "npm run build"
// }
// }
// 連結:&&(失敗で中断)
// 並列:& または concurrently ライブラリ
// pre/post フック:prebuild は build 前に自動実行
// npx で一時実行:npx vitest

설정과 환경

dotenv로 .env 로드, 타입화된 설정 객체, 런타임 검증. 설정과 코드 분리.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// インストール:npm i dotenv
// import 'dotenv/config';
const port = Number(process.env.PORT ?? 3000);
const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) {
throw new Error('缺少 DATABASE_URL');
}
// 型付き設定:
interface Config {
port: number;
debug: boolean;
apiKey: string;
}
// バリデーション関数が Config を返し、型を保証
// .env はバージョン管理外(gitignore)
// 環境差分:.env.development / .env.production

18.정규식과 텍스트 처리

정규식 문법, 플래그, 타입화된 매칭과 텍스트 처리 관용구.

정규식 문법

리터럴 /.../ 또는 RegExp 생성. 문자 클래스, 수량자, 그룹, 앵커.

1
2
3
4
5
6
7
8
9
const re = /\b\w+@\w+\.com\b/;
// \d 数字 \w 単語 \s 空白 \b 単語境界
// [abc] 文字クラス [^abc] 否定
// * 0 回以上 + 1 回以上 ? 0 または 1 {2,4} 区間
// ^ 先頭 $ 末尾
// () グループ (?:) 非キャプチャ
// または:/cat|dog/
// テスト:
re.test('hi [email protected]'); // true

플래그

g 전역, i 대소문자 무시, m 다중 행, s 점이 줄바꿈 매칭, u 유니코드, y 고정.

1
2
3
4
5
6
7
8
9
10
const g = /a/g; // グローバル(matchAll に必要)
const i = /HELLO/i; // 大文字小文字無視
const m = /^line/m; // 各行のアンカー
const s = /a.b/s; // . が改行にもマッチ
const u = /\p{Emoji}/u; // unicode プロパティ
const y = /a/y; // スティッキー(lastIndex から)
// 組み合わせ:/foo/gim
// 動的構築:
new RegExp(`\\d{${len}}`, 'gi');
// リテラルで \ はエスケープ必須

매칭과 추출

match는 배열 반환(0 전체 매칭 + 캡처 그룹), matchAll은 전역 순회, match 실패 시 null이므로 null 확인 필요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const s = 'id=123&id=456';
const re = /id=(\d+)/g;
// 全件マッチ:
for (const m of s.matchAll(re)) {
console.log(m[1]); // '123' '456'
}
// 単発:
const first = s.match(re);
if (first) { console.log(first[0]); }
// 名前付きキャプチャ:
const named = /(?<year>\d{4})-(?<month>\d{2})/;
const r = s.match(named);
if (r) { r.groups!.year; }
// 最小マッチ ?:/(\d+?)(x)/ で最少マッチ

치환

replace는 문자열/함수 치환. $1 캡처 참조, g 플래그로 전체 치환. 함수형 치환으로 로직 처리.

1
2
3
4
5
6
7
8
9
10
11
const s = '2026-08-02';
// キャプチャ参照:
const a = s.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3/$2/$1');
// 関数で置換:
const b = s.replace(/(\d+)/g, (m) => String(Number(m) + 1));
// 全置換(g 必須):
'aaa'.replace(/a/g, 'b'); // 'bbb'
// 空白除去:
s.replace(/\s+/g, ' ').trim();
// 単純置換は split/join も可:
s.split('-').join('/');

검증 관용구

전체 매칭은 ^...$ 앵커 사용. 숫자/이메일/URL의 일반적인 패턴. test는 boolean 반환.

1
2
3
4
5
6
7
8
9
10
11
12
13
function isEmail(v: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v);
}
function isInt(v: string): boolean {
return /^[-+]?\d+$/.test(v);
}
function isUrl(v: string): boolean {
try { new URL(v); return true; }
catch { return false; }
}
// 厳密一致は ^ で始まり $ で終わる必須
// 長さチェック:/^.{8,20}$/
// 貪欲を回避:/^\.$/ でドットをマッチ

정규식 성능

재앙적 백트래킹 방지: 중첩 수량자. 정규식 사전 컴파일. g 플래그의 lastIndex 상태 주의.

1
2
3
4
5
6
7
8
9
10
11
// BAD:壊滅的バックトラック
// /^(a+)+$/ が 'aaaaaaaaaaaaaaaaaaaa!' にマッチするのは極めて遅い
// GOOD:ネストした量詞を避ける
/^(a+)$/;
// 事前コンパイルで再生成を避ける:
const re = /\d+/g; // モジュールレベルで再利用
// g フラグは状態を持つ:
re.lastIndex = 0; // リセット
// 大きなテキストはチャンク処理
// 単純パースは indexOf / split を優先
// 正規表現は構造マッチのみ、ビジネスロジックはコードで

정규식 일반적인 함정

리터럴 이스케이프, g 플래그의 lastIndex 상태, 탐욕적 매칭, 문자열에서 \의 이중 이스케이프.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 文字列構築時 \ は 2 回書く:
new RegExp('\\d+'); // /\d+/ と同等
// g フラグは lastIndex 状態を持つ:
const re = /a/g;
re.lastIndex = 0; // 使用前にリセット
// 貪欲マッチ:
'<a><b>'.match(/<.*>/); // 最後の > までマッチ
'<a><b>'.match(/<.*?>/); // 非貪欲、最短
// リテラル . はエスケープ:
/1\.0/; // '1.0' にマッチ、'1X0' ではない
// [] 内の ^ は否定:
/[^a]/; // a 以外
// 空マッチ:/(?:)/ は任意の位置にマッチ

일반적인 패턴

신분증/휴대폰 번호/색상/날짜 등의 일반적인 정규식 조각. 비즈니스 형식 검증에 매칭.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 携帯番号(中国大陸):
const mobile = /^1[3-9]\d{9}$/;
// メール:
const email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// 16 進数カラー:
const color = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
// 日付 yyyy-mm-dd:
const date = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
// URL:
const url = /^https?:\/\/[^\s]+$/;
// 中文字符:
const zh = /[\u4e00-\u9fff]/;
// 空行:
const blank = /^\s*$/;
// 記憶要点:^$ アンカー、数量限定、文字クラス

19.빌드와 엔지니어링

tsconfig, 번들링 도구, Lint/포맷, 테스트와 CI.

tsconfig 상세

일반적인 컴파일 옵션: moduleResolution, declaration, noUnusedLocals, esModuleInterop, paths 경로 별칭.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2022", "DOM"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"declaration": true, // .d.ts を生成
"outDir": "dist",
"noUnusedLocals": true,
"paths": { "@/*": ["./src/*"] },
"resolveJsonModule": true
},
"include": ["src"]
}
// npm-run: tsc --noEmit で型チェック

번들링 도구

Vite/Webpack/Rollup 번들링. Vite는 TS/프론트엔드 기본. 라이브러리는 tsup/Rollup으로 ESM+CJS 출력.

1
2
3
4
5
6
7
8
9
10
11
12
// Vite:dev サーバー + ビルド
// vite.config.ts:
export default {
build: { target: 'esnext' },
// plugins: [react(), vue()]
};
// コマンド:
// npm run dev 開発
// npm run build ビルド
// ライブラリビルド:tsup
// tsup src/index.ts --format esm,cjs --dts
// 環境変数:import.meta.env.VITE_XXX

Lint와 포맷

ESLint 규칙 검사, Prettier 포맷. ts-eslint은 타입 인식 규칙 제공.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ESLint 設定:
// {
// "parser": "@typescript-eslint/parser",
// "plugins": ["@typescript-eslint"],
// "rules": {
// "@typescript-eslint/no-explicit-any": "warn"
// }
// }
// コマンド:
// npx eslint src --fix
// Prettier:
// npx prettier --write "src/**/*.ts"
// ルールテンプレート:
// npx eslint --init
// コミット前:husky + lint-staged

테스트

Vitest/Jest 단위 테스트. describe/it/expect. 타입과 실행 분리. ts 직접 테스트.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { describe, it, expect } from 'vitest';
import { add } from './add';
describe('add', () => {
it('两数相加', () => {
expect(add(1, 2)).toBe(3);
});
it('类型错误编译失败', () => {
// add('a', 2) // コンパイル時にブロック
});
});
// 型テスト:
// import { expectType } from 'tsd';
// カバレッジ:vitest run --coverage
// Mock:vi.mock() / vi.fn()

CI와 배포

CI 단계: 타입 검사, Lint, 테스트, 빌드. tsc --noEmit으로 타입 오류 차단.

1
2
3
4
5
6
7
8
9
10
11
// GitHub Actions:
// steps:
// - run: npm ci
// - run: npx tsc --noEmit # 型チェック
// - run: npx eslint src
// - run: npm test
// - run: npm run build
// - run: npm publish --dry-run
// 型チェックを最初に:失敗ですぐに中断
// キャッシュ:actions/cache で依存を高速化
// マルチバージョン:node 18/20/22 マトリクス

디버깅

sourceMap + Node inspect 중단점 디버깅. console 디버깅, 타입 단언 보조.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// tsconfig sourceMap: true
// VS Code launch.json:
// {
// "type": "node",
// "request": "launch",
// "program": "${file}",
// "runtimeArgs": ["--loader", "tsx"]
// }
// コマンド:
// node --inspect dist/main.js
// ブラウザ:DevTools Sources + sourcemap
// 型のデバッグ:
// type Debug<T> = T; hover で確認
// console 出力で位置特定をサポート

npm 배포

라이브러리 배포: files로 배포 내용 지정, version 시맨틱, main/types/exports 진입점. 배포 전 빌드.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// package.json:
// {
// "name": "@org/my-lib",
// "version": "1.2.0",
// "main": "./dist/index.js",
// "types": "./dist/index.d.ts",
// "exports": {
// ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs" }
// },
// "files": ["dist"],
// "sideEffects": false
// }
// 公開:
// npm run build && npm publish
// ドライラン:npm publish --dry-run
// バージョン:npm version patch|minor|major
// 権限:npm publish --access public

monorepo 설정

npm/pnpm workspaces 다중 패키지 저장소. 공유 의존성, 패키지 간 참조, 통합 스크립트.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// pnpm-workspace.yaml:
// packages:
// - 'packages/*'
// - 'apps/*'
// npm workspaces:
// {
// "workspaces": ["packages/*"]
// }
// パッケージ間参照:
// npm i @org/shared -w packages/web
// ルートスクリプトで一括:
// pnpm -r run build
// 共通 TS 設定:
// tsconfig.base.json を各パッケージが extends
// 依存ホイスト:pnpm はデフォルト隔離、明示宣言が必要

공식 링크

공식 문서와 리소스에 대한 직접 링크.

이 치트시트에 대해

이 페이지는 TypeScript 5.x의 자체 완비된 참조 매뉴얼로, 실제 프로젝트에서 타입 시스템과 언어 핵심의 약 80%의 일반적인 사용법을 다룸. 내용은 현대적 관용구를 중심으로 함: 인터페이스와 타입 별칭, 제네릭, 유니온/교차 타입, 타입 좁히기, 리터럴 타입, keyof/typeof, 매핑 타입과 조건부 타입, 그리고 비동기 프로그래밍과의 결합. TypeScript는 Microsoft에서 2012년에 출시되었으며, JavaScript의 상위 집합으로, 컴파일 타임에 JavaScript에 정적 타입 검사를 추가하여 대규모 프로젝트의 유지보수성을 크게 향상시키며, 현재 프론트엔드 엔지니어링의 주류 선택임. 19개 챕터는 각각 하나의 주제에 집중함: 기본 문법, 변수와 타입 추론, 타입 시스템, 참조와 값 의미, 제어 흐름, 함수와 오버로드, 문자열과 템플릿, 컬렉션, 메모리와 타입 소거, 클래스와 인터페이스, 오류 처리, 입출력, 일반적인 오해, 동시성(비동기 타입), 네트워크, 시간, 프로세스, 정규식과 빌드 도구(tsc/tsconfig). 각 섹션은 '개념 소개 + 바로 복사 가능한 코드 스니펫'으로 구성됨. 모든 코드와 텍스트는 브라우저에서 로컬로 렌더링되며, 어떤 데이터도 기기를 떠나지 않음. 권위 있는 참고 자료는 TypeScript 공식 매뉴얼을 참조.

버전 2.1.0