SHIN STORYSHIN STORY
홈포스트C#TypeScriptNext.jsNode.js시리즈
</>SHIN STORY

sdf

탐색

  • 홈
  • 모든 포스트
  • 시리즈
  • 검색

카테고리

  • C#
  • TypeScript
  • Next.js
  • Node.js
  • 알고리즘
  • 개발 도구

© 2025 Shin Blog. All rights reserved.

GitHubRSS
목록으로
TypeScript#TypeScript

TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

SHIN

2025년 4월 29일2분 읽기0
📚

TypeScript 실전 팁 10선

10편
  1. 5TypeScript 팁 #5 — 타입 가드로 런타임 타입 좁히기
  2. 6TypeScript 팁 #6 — 매핑 타입으로 타입 변환하기
  3. 10TypeScript 팁 #1 — strict 모드를 반드시 켜야 하는 이유
  4. 10TypeScript 팁 #2 — 유틸리티 타입 완전 정복
  5. 10TypeScript 팁 #3 — 판별 유니온으로 타입 안전한 상태 관리
  6. 10TypeScript 팁 #4 — 제네릭 제약 조건과 infer 활용
  7. 10TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작
  8. TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기현재
  9. 10TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴
  10. 10TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

TypeScript 팁 #8 — 선언 병합과 모듈 보강으로 타입 확장하기

인터페이스 선언 병합

같은 이름의 인터페이스를 여러 번 선언하면 자동으로 합쳐집니다.

CODE
interface User {
  id: number
  name: string
}

interface User {
  email: string
}

// 결과: { id: number; name: string; email: string }
const user: User = { id: 1, name: '홍', email: 'hong@example.com' }

type 별칭은 병합이 불가능하지만, interface는 가능합니다. 라이브러리 타입 확장에 유용합니다.

모듈 보강 (Module Augmentation)

외부 라이브러리 타입을 직접 수정하지 않고 확장할 수 있습니다.

Express Request에 사용자 정보 추가

CODE
// src/types/express.d.ts
import { User } from './user'

declare global {
  namespace Express {
    interface Request {
      user?: User
      requestId: string
    }
  }
}

// 미들웨어에서
app.use((req, res, next) => {
  req.user = getCurrentUser()  // ✅ 타입 오류 없음
  req.requestId = generateId()
  next()
})

Next-Auth 세션 타입 확장

CODE
// src/types/next-auth.d.ts
import 'next-auth'

declare module 'next-auth' {
  interface Session {
    user: {
      id: string
      role: 'admin' | 'user'
      name?: string | null
      email?: string | null
    }
  }

  interface User {
    role: 'admin' | 'user'
  }
}

declare module 'next-auth/jwt' {
  interface JWT {
    role: 'admin' | 'user'
  }
}

Window 객체 확장

CODE
// src/types/global.d.ts
declare global {
  interface Window {
    gtag: (command: string, ...args: any[]) => void
    dataLayer: any[]
  }
}

// 사용
window.gtag('event', 'page_view')  // ✅

환경 변수 타입 안전 처리

CODE
// src/types/env.d.ts
declare global {
  namespace NodeJS {
    interface ProcessEnv {
      NODE_ENV: 'development' | 'production' | 'test'
      DATABASE_URL: string
      NEXTAUTH_SECRET: string
      NEXT_PUBLIC_SITE_URL: string
      // 선택적 변수
      ANALYTICS_ID?: string
    }
  }
}

// 이제 process.env.DATABASE_URL은 string | undefined 아닌 string
const url: string = process.env.DATABASE_URL  // ✅

라이브러리 타입 버그 수정

라이브러리 타입 정의에 버그가 있을 때 모듈 보강으로 임시 수정합니다.

CODE
// 잘못된 타입을 가진 라이브러리 수정
declare module 'some-library' {
  interface Options {
    timeout: number  // 기존에는 없던 필드 추가
    onError?: (err: Error) => void  // 잘못된 타입 수정
  }
}

interface vs type 선택 기준

상황선택
외부 라이브러리 확장interface (병합 가능)
유니온 타입type
튜플 타입type
함수 타입type 또는 interface
클래스 구현체interface
단순 객체 형태둘 다 가능

모듈 보강은 @types 패키지를 직접 수정하거나 라이브러리를 fork하지 않고도 타입 문제를 해결할 수 있는 깔끔한 방법입니다.

공유
S

SHIN

.NET 개발자입니다

GitHub
TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작

이전 포스트

TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작

다음 포스트

TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

같은 카테고리 포스트

TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

TypeScript 팁 #10 — 타입 성능 최적화와 실무 패턴

2025년 5월 3일· 3분
TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

TypeScript 팁 #9 — 타입 안전한 에러 처리 패턴

2025년 5월 1일· 2분
TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작

TypeScript 팁 #7 — 템플릿 리터럴 타입으로 문자열 타입 조작

2025년 4월 27일· 2분

댓글