用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/puk0806/gugbab-claude --skill typescript-v4命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
DDD(Domain-Driven Design) 아키텍처 핵심 패턴 - 유비쿼터스 언어, 서브도메인, 바운디드 컨텍스트, Aggregate, Entity/VO, 도메인 서비스/이벤트, 레이어드 아키텍처
대규모 React/Next.js 프로젝트를 layer-first(types/·utils/·hooks/·api/·components/ 밑에 도메인이 반복되는 구조)에서 domain-first(feature/도메인 우선) 구조로 전환하는 설계 기준과 절차. Feature-Sliced Design 2.1 정본(layers 6종·slices·segments·import 규칙·@x 크로스임포트·public API), FSD를 쓰지 않는 경량 대안(features + shared 2~3계층 + ESLint import/no-restricted-paths), Next.js App Router 공존 전략(route group `()`·private folder `_`·colocation), Turborepo/Nx 모노레포에서 폴더↔패키지 승격 기준, colocation과 배럴 파일 성능 트레이드오프, 도메인 경계 역추출(import 그래프·change coupling·용어 클러스터), 전환 실패 패턴(shared 비대화·entities 남용·순환 의존·도메인=라우트 착각·조기 추상화). 도메인 개념 자체(바운디드 컨텍스트·유비쿼터스 언어)는 `architecture/ddd` 스킬을 참조한다.
소스 파일 수천 개 규모 프론트엔드 코드베이스를 멈추지 않고 점진 재구조화하는 실행 전략 - Strangler Fig / Branch by Abstraction / Parallel Change, ts-morph·jscodeshift codemod, PR 분할·검증 게이트·되돌리기, 테스트 없는 코드의 안전망, 작업 순서 설계와 위반 수 기반 진행 추적
正在显示 SKILL.md
| name | typescript-v4 |
| description | TypeScript 4.x (4.0~4.9) 버전별 핵심 기능, 타입 시스템 고급 패턴, tsconfig 설정 가이드 |
소스: 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(2020
2022, 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) |
튜플 타입에 스프레드를 사용하여 가변 길이 튜플을 합성할 수 있다.
type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U]
type Result = Concat<[1, 2], [3, 4]> // [1, 2, 3, 4]
// 실용 패턴: 함수 파라미터 합성
function concat<T extends unknown[], U extends unknown[]>(
a: [...T], b: [...U]
): [...T, ...U] {
return [...a, ...b] as [...T, ...U]
}
튜플 요소에 이름을 부여하여 가독성을 높인다.
// 이전: 의미 불명확
type Range = [number, number]
// 4.0+: 이름 부여
type Range = [start: number, end: number]
// 선택적 요소에도 적용
type Config = [host: string, port: number, secure?: boolean]
문자열 리터럴 타입을 템플릿으로 조합한다.
type EventName = 'click' | 'focus' | 'blur'
type Handler = `on${Capitalize<EventName>}` // 'onClick' | 'onFocus' | 'onBlur'
// 내장 문자열 유틸리티 타입 (4.1+)
type Upper = Uppercase<'hello'> // 'HELLO'
type Lower = Lowercase<'HELLO'> // 'hello'
type Cap = Capitalize<'hello'> // 'Hello'
type Uncap = Uncapitalize<'Hello'> // 'hello'
// 실용 패턴: CSS 프로퍼티 타입
type CSSUnit = 'px' | 'em' | 'rem' | '%'
type CSSValue = `${number}${CSSUnit}` // '16px', '1.5rem' 등
as 절로 매핑 시 키를 변환한다.
interface User {
name: string
age: number
email: string
}
// getter 메서드 타입 생성
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
}
type UserGetters = Getters<User>
// { getName: () => string; getAge: () => number; getEmail: () => string }
// 특정 키 필터링
type RemoveKind<T> = {
[K in keyof T as Exclude<K, 'kind'>]: T[K]
}
추상 클래스를 인자로 받는 팩토리 함수를 타입 안전하게 작성한다.
// 4.2 이전: abstract 클래스를 new로 인스턴스화 불가 에러
// 4.2+: abstract construct signature
function create<T>(Ctor: abstract new () => T): T {
// 직접 인스턴스화는 불가하지만 서브클래스는 가능
return new (Ctor as new () => T)()
}
튜플에서 rest 요소를 앞이나 중간에 배치할 수 있다.
// 마지막 요소가 고정, 앞은 가변
type Strings = [...string[], boolean]
// ['a', 'b', true] ✅
// [true] ✅
// ['a', 'b'] ❌
// 중간 rest
type Mixed = [first: string, ...middle: number[], last: boolean]
서브클래스에서 부모 메서드를 오버라이드할 때 명시한다. noImplicitOverride: true와 함께 사용한다.
class Base {
greet() { return 'hello' }
}
class Derived extends Base {
override greet() { return 'hi' } // ✅ 명시적 오버라이드
// override unknown() { } // ❌ 부모에 없는 메서드
}
tsconfig:
{
"compilerOptions": {
"noImplicitOverride": true
}
}
클래스의 static 멤버에 인덱스 시그니처를 사용할 수 있다.
class Registry {
static [key: string]: unknown
static name = 'Registry'
static version = 1
}
변수에 할당된 조건 결과를 추적하여 타입을 좁힌다.
function example(x: string | number) {
const isString = typeof x === 'string'
// 4.4 이전: isString으로 좁히기 불가
// 4.4+: aliased condition도 CFA 적용
if (isString) {
x.toUpperCase() // ✅ string으로 좁혀짐
}
}
// 배열 요소 존재 검사도 개선
function getFirst(arr: string[]) {
const first = arr[0] // string | undefined (noUncheckedIndexedAccess)
if (first !== undefined) {
first.toUpperCase() // ✅ string
}
}
Promise를 재귀적으로 언래핑하는 내장 타입이다.
type A = Awaited<Promise<string>> // string
type B = Awaited<Promise<Promise<number>>> // number
type C = Awaited<string | Promise<boolean>> // string | boolean
// 실용: Promise.all 반환 타입 추론에 활용
async function fetchAll() {
const [user, posts] = await Promise.all([
fetchUser(), // Promise<User>
fetchPosts() // Promise<Post[]>
])
// user: User, posts: Post[] — Awaited가 자동 적용
}
깊은 재귀 조건부 타입에서 스택 오버플로를 방지한다.
// 4.5 이전: 깊은 재귀 시 "Type instantiation is excessively deep" 에러
// 4.5+: tail position 재귀는 자동 최적화
type TrimLeft<T extends string> =
T extends ` ${infer Rest}` ? TrimLeft<Rest> : T
type Result = TrimLeft<' hello'> // 'hello'
구조 분해된 판별 유니온도 Control Flow Analysis가 적용된다.
type Action =
| { kind: 'increment'; amount: number }
| { kind: 'decrement'; amount: number }
| { kind: 'reset' }
function handle(action: Action) {
// 4.6+: 구조 분해 후에도 CFA 작동
const { kind } = action
if (kind === 'increment') {
// action.amount 접근 가능 ✅ (4.6+)
console.log(action.amount)
}
}
Node.js ESM 네이티브 지원을 위한 모듈 해석 전략이다.
{
"compilerOptions": {
"module": "node16",
"moduleResolution": "node16"
}
}
핵심 규칙:
.mts 파일 -> .mjs 출력 (ESM).cts 파일 -> .cjs 출력 (CJS).ts 파일 -> package.json의 type 필드에 따라 결정import { x } from './util.js'// ESM 환경 (.mts 또는 "type": "module")
import { helper } from './helper.js' // 확장자 필수
// CJS 환경 (.cts 또는 "type": "commonjs")
const { helper } = require('./helper')
제네릭 함수의 타입 파라미터를 미리 고정한다.
function makeBox<T>(value: T) {
return { value }
}
// 4.7+: 타입 인자만 고정, 호출은 나중에
const makeStringBox = makeBox<string>
// makeStringBox: (value: string) => { value: string }
const box = makeStringBox('hello') // { value: string }
{} 타입과의 교차가 더 정확하게 축소된다.
// 4.8+: NonNullable<T>가 T & {} 로 단순화
type NonNullable<T> = T & {}
// unknown이 {} | null | undefined로 분해
function narrowUnknown(x: unknown) {
if (x !== null && x !== undefined) {
x // {} 타입 (non-nullable)
}
}
타입 검증을 수행하면서 리터럴 타입 추론을 유지한다.
type Colors = Record<string, [number, number, number] | string>
// as const: 타입이 너무 좁아짐 (Colors와 호환 검증 불가)
// : Colors: 타입이 넓어져 리터럴 정보 소실
// satisfies: 양쪽 장점을 모두 확보
const palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 255]
} satisfies Colors
palette.green.toUpperCase() // ✅ string 메서드 사용 가능
palette.red.map(x => x / 255) // ✅ 튜플 메서드 사용 가능
// palette.purple // ❌ 존재하지 않는 키 에러
satisfies vs 타입 단언 vs 타입 어노테이션:
| 방식 | 타입 검증 | 리터럴 유지 |
|---|---|---|
satisfies T | O | O |
: T (어노테이션) | O | X (넓어짐) |
as T (단언) | X (위험) | X |
as const | X | O (좁아짐) |
클래스 필드에 accessor 키워드를 사용하면 getter/setter가 자동 생성된다.
class User {
accessor name: string
constructor(name: string) {
this.name = name
}
}
// 내부적으로 다음과 동일:
// get name(): string { return this.#name }
// set name(value: string) { this.#name = value }
주의: auto-accessor는 ECMAScript Stage 3 데코레이터 제안과 함께 사용되며,
useDefineForClassFields: true설정이 필요하다.
상세 레퍼런스 (예제·고급 패턴·흔한 실수) →
references/REFERENCE.md