프로그래밍프론트엔드 개발자

TypeScript에서 타입 추론(type inference) 메커니즘은 어떻게 작동하며, 언제 수동으로 이를 제어해야 하나요?

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

답변.

질문의 역사

TypeScript는 명시적인 타입을 과도하게 사용하지 않고 안전한 개발을 강조하여 설계되었습니다: 대부분의 변수, 매개변수 및 반환 값의 타입은 컴파일러가 자동으로 추론할 수 있습니다. 타입 추론 시스템(type inference)은 거의 JavaScript처럼 코드를 작성할 수 있게 하면서도 엄격한 타입 검사를 유지하여 개발 속도를 높이고 오류를 줄입니다.

문제

타입 추론은 항상 개발자가 예상하는 타입을 보장하지 않습니다. 때때로 타입이 너무 넓게(any 또는 unknown) 추론되거나, 반대로 너무 엄격하게 됩니다. 이는 불필요한 제약이나 타입 검사가 없게 되어 두 경우 모두 안전하지 않습니다.

해결책

TypeScript는 타입이 명시적으로 지정되지 않은 경우 할당 또는 함수의 반환 값을 기반으로 자동으로 타입을 추론합니다. 명시적 타입 지정, 타입 단언(type assertion), 제네릭(generics), 및 특수 유틸리티(ReturnType, Parameters 등)를 통해 추론을 제어할 수 있습니다. 복잡한 구조와 작업할 때는 특별한 주의가 필요합니다: 타입이 복잡하거나 불명확할 경우 명시적으로 지정하는 것이 좋습니다.

코드 예시:

let a = 5; // number (자동으로 추론됨) function sum(x = 4, y = 3) { // x: number, y: number return x + y; // return: number } // 타입 추론 오류 unction getData(flag) { if (flag) return 123; // 다른 분기에서 return 없음 — return type: number | undefined } // 명시적으로 지정하는 것이 좋음: function getData(flag: boolean): number | undefined { if (flag) return 123; }

주요 특징:

  • TypeScript는 초기화 및 값을 기반으로 변수를 추론합니다.
  • 함수와 객체의 경우, 명시적 지정이 없으면 타입이 너무 넓어질 수 있습니다.
  • 제네릭 및 복잡한 구조의 경우 항상 명시적으로 타입을 지정하는 것이 좋습니다.

함정이 있는 질문.

True/False: 타입 추론은 항상 개발자가 예상하는 타입을 제공합니다

False. 배열/객체/선택적 반환 값에 대해 예상보다 넓거나 좁은 타입이 발생할 수 있습니다 (number | undefined — 자주 발생하는 비 예상 결과).

객체에 타입을 명시하지 않으면 TypeScript는 항상 정확한 구조를 유지합니다

아니요, as const 없다면 구조는 "확장 가능(widened)"하게 됩니다; as const를 사용하면 readonly 및 리터럴 타입으로 됩니다.

const obj = { kind: "duck" }; // obj: { kind: string } const obj2 = { kind: "duck" } as const; // obj2: { readonly kind: "duck" }

배열에 타입을 명시하지 않으면 TS는 항상 내용을 알고 있습니다

아니요, 기본적으로 TypeScript는 배열을 최대한 "넓게" 추론합니다 — 예를 들어, let arr = [1, 'a']는 (string | number)[]가 되며, tuple이 아닙니다.

타입 오류 및 안티 패턴

  • 함수의 매개변수에 대해 타입 추론에 의존하기 — 타입은 변경될 수 있습니다.
  • 함수의 반환 값 타입을 명시하지 않기 — 유지 관리가 어렵습니다.
  • 상수 객체에 대해 as const 또는 명시적 타입을 사용하지 않기.

실생활 예시

부정적인 사례

백엔드에서 반환된 객체 { data: [] }, 타입이 명시되지 않으면 TypeScript는 data: any[]로 추론합니다. 어느 순간 data가 문자열 배열로 변경되면 — 오류는 프로덕션에서만 발생합니다.

장점:

  • 간단한 경우에 대해 수동으로 타입을 작성할 필요가 없습니다.

단점:

  • 복잡한 구조에서 비직관적인 오류가 발생할 수 있습니다.
  • 자동 추론이 문제를 "토해낼" 수 있습니다.

긍정적인 사례

프로젝트에서 항상 함수의 반환 값과 복잡한 구조의 타입을 명시적으로 지정하고, 상수에 대해 as const를 사용하는 것이 표준입니다. 어떠한 구조 변경도 컴파일러에 의해 검증됩니다.

장점:

  • API와 타입 간의 엄격한 일치.
  • 오류 변경 사항을 신속하게 식별합니다.

단점:

  • 타입 설명에 조금 더 시간이 걸릴 수 있습니다.
  • 필요하지 않은 곳에서 "과도하게" 엄격한 상황이 발생할 수 있습니다.