"기본 연산 하나로 설명할 수 없는 검증이라면, 참일 때 어떤 타입인지 함수 계약에 적어."
반환 타입의 특별한 문법
function isUser(x: unknown): x is User처럼 반환 타입에 x is User를 쓰면 타입 술어가 돼. 함수 몸은 평범한 boolean을 반환하지만, 호출 결과가 참인 분기에서는 호출자의 x가 User로 좁혀진다.
속성 여러 개의 존재와 값 타입을 함께 확인하거나 중첩된 JSON 구조를 검증할 때 유용해. 긴 검사 코드를 한 함수에 모으고, 사용하는 곳에서는 내장 좁히기처럼 읽을 수 있다.
컴파일러는 술어의 말을 믿어
중요한 함정은 TypeScript가 함수 몸이 반환 타입의 약속을 실제로 증명하는지 확인하지 못한다는 점이야. 무조건 true를 반환해도 x is User라고 적을 수 있어. 술어가 거짓말하면 그 뒤의 타입 안전도 함께 무너진다.
그래서 타입 술어는 신뢰 경계의 코드로 다뤄. 정상값뿐 아니라 빠진 속성, null, 잘못된 원시값, 중첩 오류를 테스트해. 외부 입력 검증이 커지면 Zod나 Valibot 같은 스키마 도구가 파싱과 타입 추론을 함께 관리하는 편이 낫다.
직접 술어를 쓸 자리
- JSON이나 사용자 입력처럼 타입 없는 외부 데이터를 검증할 때
- 공통 판별 필드가 없는 객체 유니언의 모양을 검사할 때
- 하나의 typeof나 instanceof로 표현하기 어려운 검사를 묶을 때
Zod, Valibot, io-ts 같은 라이브러리는 이 경계 검사 패턴을 파서와 타입 추론으로 확장해.
타입 술어는 컴파일러가 믿는 증언이야. 경계 검증처럼 테스트하고, 작고 명확한 증거만 약속해.