프로그래밍풀스택 개발자

TypeScript에서 never와 void의 차이에 대해 설명해 주세요. 각 경우에 언제, 왜 사용해야 하나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

voidnever는 TypeScript에서 다른 타입입니다:

  • void는 일반적으로 값을 반환하지 않는 함수의 반환 타입으로 사용됩니다. 즉, 함수는 실행을 완료하지만 값을 반환하지 않습니다.
  • never는 함수(또는 표현식)가 절대 성공적으로 종료되지 않음을 의미합니다: 항상 예외를 throw 하거나 결코 제어권을 반환하지 않습니다(예: 무한 루프).

예제:

function log(message: string): void { console.log(message); } function throwError(message: string): never { throw new Error(message); } function infinite(): never { while (true) {} }

never는 종종 switch-case에서 타입의 완전성을 검사하는 데 사용됩니다:

type Shape = { kind: 'circle' } | { kind: 'square' }; function getArea(shape: Shape) { switch (shape.kind) { case 'circle': return 1; case 'square': return 2; default: const _exhaustive: never = shape; // 여기서 컴파일러는 case가 빠졌으면 알려줍니다. } }

질문의 함정.

void와 never가 함수의 반환 타입으로 서로 교환 가능할 수 있나요?

답변: 아닙니다. void 타입의 함수는 undefined를 반환하거나 아무것도 반환하지 않지만 실행을 완료합니다. never 타입의 함수는 결코 성공적으로 실행을 완료하지 않습니다(오류를 발생시키거나 무한 루프에 빠집니다).

예제:

const fn: () => never = () => { // return; // 오류: 'never'로 선언된 함수는 반환해서는 안 됩니다. };

역사

분석 시스템에서 유효성 검사 함수의 반환 타입을 void로 지정했지만 항상 예외를 throw했습니다. 결과적으로 개발자들은 이 함수가 "돌아올" 수 있다고 생각하고 추가 검사를 하지 않아서 오류 처리를 놓치고 호출 체인을 잘못 구현하게 되었습니다.


역사

TypeScript 프로젝트에서 명확하게 타입이 지정된 반환 타입을 기대하는 함수를 void가 아닌 never로 정의했습니다. 이로 인해 never로 타입이 지정된 콜백을 사용하는 함수 호출 시 컴파일 오류와 API 호환성 상실이 발생했습니다.


역사

백엔드 모듈에서는 예외를 void 반환 타입을 가진 함수를 통해 던졌습니다. TypeScript로 마이그레이션한 후 이 함수 호출 이후 코드 범위를 벗어난 것에 대해 컴파일러가 경고하지 않아서 "도달할 수 없는" 코드가 여러 줄 생겼습니다. 그리고 반환 타입을 never로 변경함으로써 그러한 장소를 발견하고 코드를 더 깔끔하게 하고 논리적 오류를 피할 수 있었습니다.