타입 단언은 파서가 아니에요. 외부 응답은 바이트로 시작하고, 누군가 확인하기 전까지는 그게 어떤 변형인지 알려 주는 게 하나도 없어요.
텍스트 디코딩과 JSON 파싱이 먼저 오고, 둘 다 각자 실패할 수 있어요. 파서에서 나온 값은 unknown으로 검증 단계에 들어가야 해요.
지원하는 응답은 문자열 배열 items를 가진 ready 태그, 아니면 문자열 message를 가진 failed 태그예요. 런타임 검사는 세 가지를 확인해야 해요. 값이 객체인지, 태그가 아는 태그인지, 그 태그에 맞는 페이로드 모양을 갖췄는지요. ready인데 items가 없으면 불완전한 응답이에요. waiting이 오면 우리가 선언한 적 없는 태그고요. 유니언에 as를 붙여 봐야 둘 다 해결되지 않아요.
검사를 통과하면 디코더가 판별 유니언을 돌려줘요. ready를 확인하는 분기에서 값이 좁혀지고 항목을 쓸 수 있게 돼요. never로 하는 전수 검사는 선언된 모델에서 처리하지 않은 경우를 드러내 줘요. 유지보수에는 좋은 정보지만 응답 바이트를 들여다보지는 않아요.
거부된 입력은 어떻게 할지 정해야 해요. 디코딩 실패로 보고할지, 알 수 없는 응답을 일부러 변형 하나로 모델링할지요. 받아들인 유니언으로 슬쩍 캐스팅하면 그 결정을 건너뛰게 돼요.
런타임 근거는 타입이 붙은 값을 만드는 자리 바로 옆에 두세요. 그리고 핸들러마다 계산은 따로 리뷰해요. 분기를 다 덮어도 그 안의 계산은 틀릴 수 있으니까요.