jtwjs Dev Wiki
  • DEV_ROAD
    • 💪🏻 생존하기
    • Week 1
      • 개발 환경 세팅
      • 타입스크립트
      • 리엑트
      • Testing Library
      • Parcel & ESLint
    • Week 2
      • JSX
      • Virtual DOM
    • Week 3
      • React Component
      • React State
    • Week 4
      • Express
      • Fetch API & CORS
      • React Hook
      • useRef & Custom Hook
    • Week 5
      • TDD
      • React Testing Library
      • MSW
      • Playwrite
      • Snapshot
    • Week 6
      • Separtion of Concerns
      • Principle
      • DI, (Dependency Injection)
      • Reflect-metadata
      • TSyringe
      • External Store
      • Follow Redux
      • usestore-ts
      • useSyncExternalStore
    • Week 7
      • Routing
      • Routes
      • Router
      • Navigation
    • Week 8
      • Design System
      • Style Basics
      • CSS-in-JS
      • Styled-Components
      • Global Style & Theme
    • Week 9
      • 개발하기 전 준비
      • 상품 목록 페이지
      • 상품 상세 페이지
      • 장바구니 페이지
    • Week 10
      • 로그인
      • 로그아웃
      • 회원가입
      • 주문 목록 & 주문 상세
    • Week 11
      • 배송 정보 입력
      • 포트원 결제 요청
      • 배송 및 결제 정보 전달
    • Week 12
      • 관리자 웹사이트개발시작
  • DEV_NOTE
    • TypeScript
      • 기본적 문법
        • Enum
        • 다형성
          • Untitled
        • 구조적 타이핑
        • 제너릭 타입
        • 컨디셔널 타입
        • 함수 메서드 타이핑
        • infer로 타입스크립트의 추론 직접 활용
        • 재귀 타입
        • 템플릿 리터럴 타입
        • 추가적인 타입 검사 satisfies 연산자
        • 타입스크립트 건망증
        • 원시 자료형에도 브랜딩 기법 사용 가능
        • 타입 좁히기
        • 유용한 타입 만들기
        • 데코레이터 함수
        • 앰비언트 선언도 선언 병합이 된다.
        • 앰비언트 선언도 선언병합이 된다.
    • Testing
      • Unit Testing
      • 단위 테스트의 두 분파
      • 좋은 단위 테스트를 구성하는 4대 요소
      • 테스트 대역과 식별할 수 있는 동작
      • 단위 테스트 스타일
      • 가치 있는 단위 테스트를 위한 리팩토링
      • 통합 테스트
      • Cross Browsing Testing
      • 기능 테스트 종류
      • React Testing Pattern
      • 프론트엔드 테스트 입문
        • 테스트 범위
        • 단위 테스트 검증
        • Mock
        • UI 컴포넌트 테스트
        • 테스트 커버리지
        • 웹 통합 테스트
        • MSW
        • 스토리북
        • 시각적 회귀 테스트
        • E2E 테스트
        • Github Actions 설정
        • 깃허브 액션에서 E2E
      • 시프트 레프트
        • 테스트 기본중의 기본
        • 단위 테스트
        • 코드 복잡도
        • 리팩터링
        • 코드 리뷰
        • 통합 테스트 패턴
        • 시스템 테스트의 자동화
        • 탐색적 테스트
      • Test Tip
      • vitest
      • playwright
      • Test Data Generator
      • MSW
    • Algorithm
      • coding test
      • Data Structure
    • Next.js
      • Data Fetching
      • Hydration
      • Next 13
      • Optimization
      • Next 15
    • Tailwind
      • Tailwind CSS
      • Theme
      • Directives
      • Tool
      • Design System
    • Storybook
      • Storybook
      • CSF3
      • CDD
      • Headless Component
    • Funtional Programming
      • 함수형 프로그래밍
      • 참조 투명성
      • 부수효과
      • 함수 합성
      • 제너릭 타입 활용하기
      • 암묵적 입출력
      • 액션과 계산, 데이터
      • 계층형 설계
      • 호출 그래프
      • 함수형 설계
      • 불변성
      • 일급 함수
      • 함수형 도구
    • Git
      • Github Actions
      • Conflict
      • Branch 전략
    • Contents Format
      • Audio
    • 3D Graphic
      • 3D keyword
      • Three.js
      • Geometry
      • Material
      • Light
      • Camera
      • Decal
      • Rotation
      • Text
      • Shadow
      • Fog
      • Post Processing
      • Animation
      • Math
        • Vector Space
        • 벡터의 연산
        • 회전 계산
      • 3D 컨텐츠가 만들어지는 과정
      • R3F
      • Env
      • Scene
      • Transform
      • R3F
      • Interaction & Raycast
      • Rendering Algorithnm
      • Blender
      • Blender
    • Accessibility
      • 접근성이란
    • Interactive Web
      • Parallax
      • Canvas
      • requestAnimationFrame
      • Effect
      • HSL
      • React.js + Canvas
      • Matter.js
    • AWS
      • DevOps
      • Amplify
      • S3
      • 클라우드 컴퓨팅
        • 온프레미스와 클라우드
        • 클라우드 도입효과
        • 클라우드 컴퓨팅의 범위
        • 컴퓨팅 옵션
          • EC2 - Virtual Machin
          • ECS, EKS - Container
          • Lambda - Serverless
        • 네트워크 가상화
        • 스토리지
        • 데이터베이스
        • 데이터 수집
        • 머신 러닝 영역
        • IoT 영역
        • 블록체인 영역
      • 클라우드 아키텍처 설계
    • Network
      • Web Server & WAS
    • System Design
      • System Design
      • Component
      • 의존성을 배제한 개발
      • Error Handling
      • Architecture
        • 모노로틱 아키텍처
        • Clean Architecture
        • Layered Architecture
        • 이벤트 기반 아키텍처
      • 상황을 파악하는 메타인지
      • 중복 문제 해결하기
      • Monorepo Arhitecture
        • 모노레포 운영과 트러블슈팅
        • Module Federation
      • 코드 병목지점
      • API 대응
      • 공통 코드
      • Infra 구축
      • 모듈 기반의 개발 방식
      • Design System
        • 최소 수준의 아키텍처 설정
        • 더 효율적인 디자인시스템 만들기
        • 디자인 시스템과 UI 라이브러리 목적
        • 디자인 토큰
      • 효율적인 업무
        • 업무 프로세스 병목 파악
      • Clean Code
      • Design Pattern
        • CQRS Pattern
        • Strangler Fig Pattern
        • 데코레이터 패턴
        • 커맨드 패턴
        • 전략 패턴
        • 옵저버 패턴
      • A/B 테스팅
      • 대규모 리엑트 웹앱 개발
        • 복잡성 관리
        • 모듈성
        • 성능
        • 디자인 시스템
        • 데이터 패칭
        • 상태 관리
        • 국제화
        • 코드 조직화하기
        • 개인화 A/B 테스팅
        • 확장 가능한 웹 아키텍처
        • 테스팅
        • 툴링
        • 기술적 마이그레이션
        • 타입스크립트
        • 라우팅
        • 사용자 중심 API 디자인
        • 리액트 미래
    • Performance
      • React DevTools
      • Component 최적화
      • Page Load
      • API
    • MFA
      • MSA
      • MFA 도입하기
      • Monorepo
        • Monorepo Tool
        • Yarn Berry Workspace
        • Turborepo
      • MFA Composition
      • SPA 통합
      • Design System
      • Package Manager
        • Yarn
        • pnpm
      • Transpiler & Bundler
        • Babel
        • Rollup
        • esbuild
        • swc
        • Webpack
        • Vite
      • 분해와 통합을 위한 여러 기술 비교
    • State Management
      • Zustand
    • React v18
      • Automatic batching
      • Suspense
      • Transition
    • SEO
      • Search Engine Optimization
      • Open Graph Element
      • Metadata
    • FE Develop
      • Scrubbing
      • Clipboard
    • Refactoring
      • 리팩토링 깊게 들여다보기
      • 긴 코드 조각내기
      • 타입 코드 처리하기
      • 유사한 코드 융합하기
      • 데이터 보호
      • 코드 추가 및 제거
    • OAuth 2.0
    • Analytics
      • Mixpanel
    • ETC
      • VSCode
    • React Hook In Action
      • useContext & Provider
      • 커스텀 훅
      • 코드 분할하기 with Suspense, lazy
      • Suspense와 이미지 적재하기
      • useTransition, uesDeferredValue
      • SuspenseList
Powered by GitBook
On this page
  • 핵심 포인트
  • 제너릭
  • 제너릭 표기 위치
  • 제너릭 기본값
  • 타입 추론
  • 제너릭에 제약 걸기
  • 제너릭 제약을 사용할 때 흔히 하는 실수
  1. DEV_NOTE
  2. TypeScript
  3. 기본적 문법

제너릭 타입

핵심 포인트

  • 상수 타입 매개변수 const T - TS v5.0에 추가됨

    • 타입을 좁힐 때 사용 (ex: string을 유니온 리터럴로 추론되게 할 때)

  • 타입 매개변수와 제약(extends)을 동일하게 생각하지 마라.

    • 타입 매개변수는 제약에 대입할 수 있는 모든 타입을 의미

    • 타입 매개변수는 제약보다 더 넓은 타입, (제약이 더 좁은 타입이라 생각)

  • 강박적으로 제너릭을 쓸 필요는 없다. 특히, 원시값 타입만 사용한다면 대부분 제약을 걸지 않아도 된다.

제너릭

타입간에 중복을 제거하기 위해 제너릭을 사용

interface Person<N, A> {
  type: 'human',
  race: 'yellow',
  name: N,
  age: A,
}

interface Zero extends Person<'zero', 28> {}
interface Nero extends Person<'nero', 32> {}

// Array 타입도 제너릭
// 제너릭이 없었다면 스트링배열, 넘버배열을 따로 타입을 선언해줬어야 됬을것
interface Array<T> {
  [key: number]: T,
  length: number
  //...
}
  • 표기는 <> 로 하며 인터페이스 이름 바로 뒤에 위치

  • <> 안에 타입 매개변수를 넣어서 사용

  • 제너릭 타입으로 타입간 중복을 줄이고 재사용성을 높힘

제너릭 표기 위치

함수에서 함수 선언문이냐 표현식이냐에 따라 제너릭 표기 위치가 달라짐

함수는 제너릭표기가 인자 앞에 위치한다고 생각

const personFactoryE = <N, A>(name: N, age: A) => {
  ...
}

function personalFactoryD<N,A>(name: N, age: A) {
  ...
}
  • interface 이름<타입 매개변수들> {...}

  • type 이름<타입 매개변수들> = {...}

  • class 이름<타입 매개변수들> {...}

  • function 이름<타입 매개변수들>(...) {...}

  • const 함수이름 = <타입 매개변수들>(...) ⇒ {...}

제너릭 기본값

타입 매개변수에 기본값을 사용할 수 있다.

interface Person<N = string, A = number> {
  type: 'human',
  race: 'yellow',
  Name: N,
  age: A
}

type Person1 = Person; // Person<string, number>
type Person2 = Person<number>; // Person<number, number>
type Person3 = Person<number, boolean>; // Person<number, boolean>

타입 추론

타입스크립트는 제너릭에 직접 타입을 넣지 않아도 추론을 통해 타입을 알아 낼 수 있다.

interface Person<N, A> {
  type: 'human',
  race: 'yellow',
  Name: N,
  age: A
}

const personFactoryE = <N, A = unknown>(name: N, age: A): Person<N,A> => ({
  type: 'human',
  race: 'yellow',
  name,
  age,
})

const zero = personFactoryE('zero', 28); // const zero: Person<string, number>
  • 이처럼 타입스크립트가 추론을 통해 타입을 알아낼 수 있는 경우는 직접 <> 타입을 넣지 않아도 된다.

    • 실제로도 직접 넣지 않는 경우가 더많음

  • 타입스크립트 5.0 버전에서 상수 타입 매개변수 (const T)가 추가됨

상수 타입 매개변수

function values<T>(initial: T[]) {
  return {
    hasValue(value:T) { return initial.includes(value) }
  }
}

const savedValues = values(['a','b','c']); // T는 string[]로 추론됨
savedValues.hasValue('x'); // T가 string으로 추론되기에 'x'를 넣어도 타입 오류가 나지 않음
  • ❓T를 string 대신 'a' | 'b' | 'c' 같은 유니온으로 추론되게 하려면?

    • 타입 매개변수 앞에 const 수식어를 추가하면 타입 매개변수 T를 추론할 때 as const를 붙인 값으로 추론됨

// TS v4.9 
function values<T>(initial: readonly T[]) { //readonly 수식어로 정확한 타입을 추론하게끔 설정
  //...
}

const savedValues = values(['a','b','c'] as const); // as const 접미사로 tuple로 만듬
savedValues.hasValue('x'); // T가 'a' | 'b' | 'c' 이므로 에러 발생

// TS v5.0
function values<const T>(initial: T[]) { // 타입 매개변수 앞에 const 수식어 사용
  //...
}

const savedValues = values(['a', 'b', 'c']);
savedValues.hasValue('x'); // 타입 에러 발생

제너릭에 제약 걸기

타입 매개변수에는 제약(constraint)를 사용 가능

extends 문법으로 타입 매개변수의 제약을 표시

  • 타입의 상속을 의미하던 extends 와는 사용법이 다르므로 구분!!

  • 제약이 걸리면 제약에 어긋나는 타입은 입력할 수 없지만 제약보다 더 구체적인 타입은 입력 가능

    • 이러한 점에서 제약은 기본값과는 다르다.

interface Example<A extends number, B = string> {
  a: A,
  b: B
}
type Usecase1 = Example<string, boolean>; // 타입 에러
type Usecase2 = Example<1, boolean> // number 보다 더 구체적인 타입 입력 가능
type Usecase3 = Example<number>

// 하나의 타입 매개변수가 다른 타입 매개변수의 제약이 될 수 도 있다.
interface Example<A, B extends A> {
 //...
}

‼️ 자주 쓰이는 제약들

<T extends object> // 모든 객체
<T extends any[]> // 모든 배열
<T extends (...args: any) => any> // 모든 함수
<T extends abstract new (...args: any) => any> // 생성자 타입
<T extends keyof any> // string | number | symbol

제너릭 제약을 사용할 때 흔히 하는 실수

  • ❌ 타입 매개변수와 제약을 동일하게 생각하는 것

  • 먼저 타입 매개변수가 제약에 대입할 수 있는 타입인지를 따져보아야 한다.

  • 강박적으로 제너릭을 쓸 필요는 없다. 특히, 원시값 타입만 사용한다면 대부분 제약을 걸지 않아도 된다.

interface VO {
  value: any;
}
// ☠️ 타입 매개변수와 제약을 동일하게 생각해서 발생하는 실수
const returnVO = <T extends VO>(): T => {
  return { value: 'test' }; // Type Error
}

// 제너릭을 제거하면됨
const returnVO = (): VO => {
  return { value: 'test' };
}
  • T 는 정확히 VO가 아니라 VO에 대입할 수 있는 모든 타입을 의미

    • 따라서 { value: string, another: string }도 T가 될 수 있다.

    • 이러면 { value: string } 은 T가 아니다. 따라서 에러가 발생함.

  • 인자값의 타입은 열려있고, 반환값의 타입은 닫혀있다. (공변성, 반공변성 참고)

// ☠️ 타입 매개변수 T 에 boolean 제약이 걸려있고, 함수의 매개변수도 T 타입
function onlyBoolean<T extends boolean>(arg: T = false): T { // 인자 타입에서 에러 발생
  return arg;
}

// onlyBoolean을 유효하게 만들고 싶다면 간단하다. 제너릭을 쓰지 않으면 된다.
function onlyBoolean(arg: boolean = true): boolean {
  return arg;
}
  • never 타입 때문, never는 모든 타입에 대입할 수 있으므로 never extends boolean은 참이다.

  • 따라서 T가 never 일 수 있으므로 false를 기본값으로 넣는 것이 불가능한 것

Previous구조적 타이핑Next컨디셔널 타입

Last updated 5 months ago