| name | typescript-v4 |
| description | TypeScript 4.x (4.0~4.9) 버전별 핵심 기능, 타입 시스템 고급 패턴, tsconfig 설정 가이드 |
TypeScript 4.x 핵심 기능 가이드
소스: https://www.typescriptlang.org/docs/handbook/release-notes/overview.html
검증일: 2026-08-26 (최초 2026-04-20 · 08-26 freshness 재검증: 4.0~4.9 기능 서술은 역사적 사실이라 변경 없음, 아래 레거시 배너 추가)
주의: 이 스킬은 TypeScript 4.x(20202022, 4.04.9)에 고정된 레거시 프로젝트용 레퍼런스다.
현재 TypeScript는 6.0(2026-03, JS 기반 마지막 메이저)을 거쳐 7.0(2026-07 GA, Go 네이티브 컴파일러) 이 최신이며, 4.x는 최신 대비 메이저 3개 뒤처져 있다
(Microsoft는 버전별 공식 EOL 일정을 문서화하지 않으므로 "EOL"로 단정하지 않는다). 신규·현행 프로젝트와 5.x 이상으로의 업그레이드 경로는 frontend/typescript-v5 스킬을 참조한다.
package.json의 typescript가 4.x인 프로젝트에서만 이 스킬을 우선한다.
버전별 주요 기능 요약
| 버전 | 핵심 기능 |
|---|
| 4.0 | Variadic Tuple Types, Labeled Tuple Elements |
| 4.1 | Template Literal Types, Key Remapping in Mapped Types |
| 4.2 | Abstract Construct Signatures, Leading/Middle Rest Elements |
| 4.3 | override 키워드, Static Index Signatures |
| 4.4 | Control Flow Analysis 개선 (aliased conditions) |
| 4.5 | Awaited 유틸리티 타입, Tail-Recursion 조건부 타입 최적화 |
| 4.6 | Destructured Discriminated Unions CFA |
| 4.7 | node16/nodenext moduleResolution, Instantiation Expressions |
| 4.8 | Intersection Reduction 개선, {} 타입 좁히기 |
| 4.9 | satisfies 연산자, Auto-Accessors (Stage 3) |
4.0: Variadic Tuple Types
튜플 타입에 스프레드를 사용하여 가변 길이 튜플을 합성할 수 있다.
type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U]
type Result = Concat<[1, 2], [3, 4]>
function concat<T extends unknown[], U extends unknown[]>(
a: [...T], b: [...U]
): [...T, ...U] {
return [...a, ...b] as [...T, ...U]
}
Labeled Tuple Elements
튜플 요소에 이름을 부여하여 가독성을 높인다.
type Range = [number, number]
type Range = [start: number, end: number]
type Config = [host: string, port: number, secure?: boolean]
4.1: Template Literal Types
문자열 리터럴 타입을 템플릿으로 조합한다.
type EventName = 'click' | 'focus' | 'blur'
type Handler = `on${Capitalize<EventName>}`
type Upper = Uppercase<'hello'>
type Lower = Lowercase<'HELLO'>
type Cap = Capitalize<'hello'>
type Uncap = Uncapitalize<'Hello'>
type CSSUnit = 'px' | 'em' | 'rem' | '%'
type CSSValue = `${number}${CSSUnit}`
Key Remapping in Mapped Types
as 절로 매핑 시 키를 변환한다.
interface User {
name: string
age: number
email: string
}
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
}
type UserGetters = Getters<User>
type RemoveKind<T> = {
[K in keyof T as Exclude<K, 'kind'>]: T[K]
}
4.2: Abstract Construct Signatures
추상 클래스를 인자로 받는 팩토리 함수를 타입 안전하게 작성한다.
function create<T>(Ctor: abstract new () => T): T {
return new (Ctor as new () => T)()
}
Leading / Middle Rest Elements
튜플에서 rest 요소를 앞이나 중간에 배치할 수 있다.
type Strings = [...string[], boolean]
type Mixed = [first: string, ...middle: number[], last: boolean]
4.3: override 키워드
서브클래스에서 부모 메서드를 오버라이드할 때 명시한다. noImplicitOverride: true와 함께 사용한다.
class Base {
greet() { return 'hello' }
}
class Derived extends Base {
override greet() { return 'hi' }
}
tsconfig:
{
"compilerOptions": {
"noImplicitOverride": true
}
}
Static Index Signatures
클래스의 static 멤버에 인덱스 시그니처를 사용할 수 있다.
class Registry {
static [key: string]: unknown
static name = 'Registry'
static version = 1
}
4.4: Control Flow Analysis 개선
변수에 할당된 조건 결과를 추적하여 타입을 좁힌다.
function example(x: string | number) {
const isString = typeof x === 'string'
if (isString) {
x.toUpperCase()
}
}
function getFirst(arr: string[]) {
const first = arr[0]
if (first !== undefined) {
first.toUpperCase()
}
}
4.5: Awaited 유틸리티 타입
Promise를 재귀적으로 언래핑하는 내장 타입이다.
type A = Awaited<Promise<string>>
type B = Awaited<Promise<Promise<number>>>
type C = Awaited<string | Promise<boolean>>
async function fetchAll() {
const [user, posts] = await Promise.all([
fetchUser(),
fetchPosts()
])
}
Tail-Recursion 조건부 타입 최적화
깊은 재귀 조건부 타입에서 스택 오버플로를 방지한다.
type TrimLeft<T extends string> =
T extends ` ${infer Rest}` ? TrimLeft<Rest> : T
type Result = TrimLeft<' hello'>
4.6: Destructured Discriminated Unions CFA
구조 분해된 판별 유니온도 Control Flow Analysis가 적용된다.
type Action =
| { kind: 'increment'; amount: number }
| { kind: 'decrement'; amount: number }
| { kind: 'reset' }
function handle(action: Action) {
const { kind } = action
if (kind === 'increment') {
console.log(action.amount)
}
}
4.7: Node16 / NodeNext Module Resolution
Node.js ESM 네이티브 지원을 위한 모듈 해석 전략이다.
{
"compilerOptions": {
"module": "node16",
"moduleResolution": "node16"
}
}
핵심 규칙:
.mts 파일 -> .mjs 출력 (ESM)
.cts 파일 -> .cjs 출력 (CJS)
.ts 파일 -> package.json의 type 필드에 따라 결정
- 상대 임포트 시 파일 확장자 필수:
import { x } from './util.js'
import { helper } from './helper.js'
const { helper } = require('./helper')
Instantiation Expressions
제네릭 함수의 타입 파라미터를 미리 고정한다.
function makeBox<T>(value: T) {
return { value }
}
const makeStringBox = makeBox<string>
const box = makeStringBox('hello')
4.8: Intersection Reduction 개선
{} 타입과의 교차가 더 정확하게 축소된다.
type NonNullable<T> = T & {}
function narrowUnknown(x: unknown) {
if (x !== null && x !== undefined) {
x
}
}
4.9: satisfies 연산자
타입 검증을 수행하면서 리터럴 타입 추론을 유지한다.
type Colors = Record<string, [number, number, number] | string>
const palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 255]
} satisfies Colors
palette.green.toUpperCase()
palette.red.map(x => x / 255)
satisfies vs 타입 단언 vs 타입 어노테이션:
| 방식 | 타입 검증 | 리터럴 유지 |
|---|
satisfies T | O | O |
: T (어노테이션) | O | X (넓어짐) |
as T (단언) | X (위험) | X |
as const | X | O (좁아짐) |
Auto-Accessors (Stage 3)
클래스 필드에 accessor 키워드를 사용하면 getter/setter가 자동 생성된다.
class User {
accessor name: string
constructor(name: string) {
this.name = name
}
}
주의: auto-accessor는 ECMAScript Stage 3 데코레이터 제안과 함께 사용되며, useDefineForClassFields: true 설정이 필요하다.
상세 레퍼런스 (예제·고급 패턴·흔한 실수) → references/REFERENCE.md