TypeScript 핵심 개념 정리: 유틸리티 타입, Zod, ! 연산자 꿀팁
TS(TypeScript) 필수 개념 정리 및 실무 활용 팁을 제공하며, 면접 및 라이브 코딩 대비에 도움을 줌
유틸리티 타입(Utility Type)과 ReactNode 활용법을 소개하고, ! 연산자 남발을 줄이는 방법을 제시
Zod를 활용한 타입 안전성 확보 및 런타임 검증 방법을 설명하며, 기존 방식의 불편함을 개선
타입 에러(Type Error) 해결을 위한 대안으로 옵셔널 체이닝, 널 병합 연산자, 조건부 연산자, 타입 가드 등을 제시
Zod의 z.infer를 활용하여 스키마와 타입 간의 일관성을 유지하고, 코드 중복을 줄이는 방법을 제시
원시 타입, 리터럴 타입, 타입 별칭, 인덱스 시그니처
TS(TypeScript)의 기본 개념인 원시 타입(Primitive Type)과 리터럴 타입(Literal Type)은 타입 시스템의 기초를 형성한다. 원시 타입은 number, string, boolean, null, undefined와 같이 단일 값을 저장하며, 리터럴 타입은 특정 값으로 타입을 정의하여 유니온 타입과 결합하여 활용성을 높인다.
타입 별칭(Type Alias)은 type 또는 interface를 사용하여 타입에 이름을 부여하고 재사용성을 높이는 방법이다. interface는 객체 타입 선언에 특화되어 선언 병합이 가능하며, type은 유니온, 튜플, 리터럴 등 다양한 타입 표현이 가능하다.
인덱스 시그니처(Index Signature)는 객체의 key를 미리 알 수 없을 때 key와 value의 타입 규칙을 정의하는 방식으로, 동적으로 확장되는 key-value 데이터를 표현할 때 유용하다.
타입 추론, 단언, 좁히기
TS(TypeScript)는 타입 추론(Type Inference)을 통해 코드의 값과 문맥을 기반으로 타입을 자동으로 결정한다. 개발자가 타입을 명시하지 않아도 TS가 초기값을 기준으로 타입을 추론하며, 함수의 반환 타입 역시 return 값을 기준으로 자동 추론된다.
타입 단언(Type Assertion)은 개발자가 컴파일러에게 특정 타입임을 직접 알려주는 방식이다. document.getElementById() 메서드의 반환 타입이 HTMLElement | null로 정의되어 있지만, HTMLDivElement임을 확신하는 경우 as HTMLDivElement를 사용하여 타입을 단언할 수 있다.
타입 좁히기(Type Narrowing)는 여러 타입이 가능한 값에서 조건문을 통해 타입 범위를 구체적으로 줄이는 과정이다. typeof, Array.isArray와 같은 타입 가드(Type Guard)를 사용하여 분기 내부에서 타입을 좁힐 수 있다.
제네릭(Generic)과 유틸리티 타입
제네릭(Generic)은 타입을 미리 고정하지 않고, 사용하는 시점에 타입을 전달받아 재사용하는 방식이다. number, string 전용으로만 동작하는 배열이나 함수에 제네릭을 사용하면, 같은 로직을 여러 타입에 적용할 수 있어 재사용성을 높일 수 있다.
유틸리티 타입(Utility Type)은 맵드 타입 기반과 조건부 타입 기반으로 나뉜다. 맵드 타입 기반에는 Partial, Required, Readonly, Pick, Omit, Record가 있으며, 조건부 타입 기반에는 Exclude, Extract, ReturnType이 있다.
Pick 유틸리티 타입을 예시로, 기존 타입에서 특정 프로퍼티만 선택하여 새로운 타입을 정의할 수 있다. Omit을 사용하면 특정 프로퍼티를 제외할 수 있으며, Pick과 교차 타입(&)을 조합하여 기존 타입을 재사용하면서 구조를 확장할 수 있다.
ReactNode와 느낌표 연산자(!)
ReactNode**는 컴포넌트가 렌더링 할 수 있는 모든 것을 포함하는 가장 넓은 범위의 타입으로, 문자열, 숫자, null, undefined, ReactElement까지 포함한다. children의 props 타입으로 주로 사용되며, 재사용성과 확장성을 고려할 때 유용하다.
느낌표 연산자(!)는 특정 값이 null이나 undefined가 아님을 개발자가 컴파일러에게 단언하는 문법이다. 타입 검사 단계에서만 동작하며, 런타임에서는 검증을 수행하지 않으므로 주의해야 한다.
! 연산자 남발은 런타임 에러의 원인이 될 수 있으므로, 옵셔널 체이닝(?.), 널 병합 연산자(??), 조건부 연산자, 타입 가드 등을 활용하여 안전하게 코드를 작성해야 한다.
Zod를 활용한 타입 안전성 확보
Zod는 TypeScript-first 스키마 유효성 검사 라이브러리로, 정적 타입 추론과 런타임 검증을 함께 제공한다. 백엔드 API에서 넘어오는 데이터나 폼 데이터를 다룰 때, Zod를 사용하면 선언적인 스키마로 데이터 형태를 정의하고 검증할 수 있다.
기존 방식의 불편함: 수동 검증, 기본값 처리, 에러 처리가 많아 스파게티 코드가 발생할 수 있다.
Zod를 사용한 방식: 선언적인 방식으로 데이터의 형태인 Schema를 정의하고 검증하며, UserSchema.parse(data) 한 줄로 런타임 검증을 완료할 수 있다.
z.infer를 활용하면 Zod 스키마로부터 TypeScript 타입을 추론하여, 스키마와 타입 간의 일관성을 유지하고 코드 중복을 줄일 수 있다. 필드가 추가되거나 타입이 바뀌어도 UserSchema만 수정하면 User 타입도 함께 갱신된다.