▶ AI시대에서 개발자가 사는 법

2분 읽기
Last updated on

Typescript 오버로드 문제해결


🚨 문제 상황

타입스크립트로 코드를 만들다가 문제가 발생했다.

원본 코드

const serviceCodes = computed(() => {
  if(!props.rentcar) return [];
  if(!props.rentcar.srvcCodes) return [];
  
  const result = props.rentcar.srvcCodes.reduce((acc, currentValue) => {
    const values = currentValue.split(',').filter(Boolean); // 콤마로 분리하고 빈 문자열 제거
    return acc.concat(values); // 결과 배열에 값 추가
  }, []);
  
  return result;
})

❌ 발생한 에러

위 코드에서 return acc.concat(values); 부분의 values에서 에러가 발생했다.

에러 메시지

오버로드 1/2('(...items: ConcatArray<never>): never')에서 다음 오류가 발생했습니다.
오버로드 2/2('(...items: ConcatArray<never>): never')에서 다음 오류가 발생했습니다.
ts(2769)

🔍 원인 분석

이 에러는 애매한 타입 추론으로 인해 발생한 것이다.

TypeScript가 reduce 함수의 초기값 []에서 배열의 타입을 추론하지 못해서 never[] 타입으로 추론하게 되었고, 이로 인해 concat 메서드가 제대로 동작하지 않는 것이다.

문제의 핵심

  • acc의 타입이 명확하지 않음
  • TypeScript가 빈 배열 []의 타입을 never[]로 추론
  • concat 메서드가 never[] 타입에 대해 작동하지 않음

✅ 해결 방법

acc에 대한 타입만 명확하게 지정해주면 된다.

수정된 코드

const serviceCodes = computed(() => {
  if (!props.rentcar) return [];
  if (!props.rentcar.srvcCodes) return [];
  
  const result = props.rentcar.srvcCodes.reduce((acc: string[], currentValue) => {
    const values = currentValue.split(',').filter(Boolean);
    return acc.concat(values);
  }, []);
  
  return result;
});

변경 사항

  • acc에 명확한 string[] 타입을 지정
  • 이제 TypeScript가 올바르게 타입을 추론할 수 있음

🎯 다른 해결 방법들

방법 1: 초기값에 타입 지정

const result = props.rentcar.srvcCodes.reduce((acc, currentValue) => {
  const values = currentValue.split(',').filter(Boolean);
  return acc.concat(values);
}, [] as string[]);  // 초기값에 타입 지정

방법 2: 제네릭 사용

const result = props.rentcar.srvcCodes.reduce<string[]>((acc, currentValue) => {
  const values = currentValue.split(',').filter(Boolean);
  return acc.concat(values);
}, []);

방법 3: spread 연산자 사용

const result = props.rentcar.srvcCodes.reduce((acc: string[], currentValue) => {
  const values = currentValue.split(',').filter(Boolean);
  return [...acc, ...values];  // concat 대신 spread 연산자
}, []);

💡 교훈

  1. TypeScript에서는 명확한 타입 지정이 중요하다

    • 특히 빈 배열 같은 경우 타입 추론이 애매할 수 있음
  2. reduce 함수 사용시 초기값의 타입을 명시하자

    • 복잡한 타입 추론 오류를 방지할 수 있음
  3. 에러 메시지를 잘 읽자

    • “never” 타입이 나오면 대부분 타입 추론 실패를 의미

📚 참고사항

TypeScript의 타입 추론

TypeScript는 대부분의 경우 타입을 자동으로 추론하지만, 다음과 같은 경우에는 명시적인 타입 지정이 필요하다:

  • 빈 배열 초기화
  • 복잡한 제네릭 함수 사용
  • 오버로드가 많은 메서드 사용

결론: 타입을 명확히 하면 대부분의 TypeScript 오류는 해결된다! 🎉