사툰사툰

함수 타입 선언하기
TYPESCRIPT

함수 타입 선언하기

타입스크립트에서 함수 타입을 선언할 때 헷갈렸던 부분을 기록했습니다.

2023. 6. 27.

920

헷갈렸던 함수 타입 선언

다음은 실제로 인턴 업무를 진행하던 중 헷갈렸던 내용이다

화살표 함수

type ReturnBtnComponent = (props: IHeaderBtn) => React.ReactElement;

// 1. 화살표 함수로 작성했을 때
// 정상 작동
export const HeaderButton : ReturnBtnComponent = (props: IHeaderBtn) => {
  const { onClick } = props;

  return (
    <div>{ButtonContents}</div>
  )
}

export default HeaderButton;

일반 함수

type ReturnBtnComponent = (props: IHeaderBtn) => React.ReactElement;

// 2. 일반 함수로 작성했을 때
// 에러 발생!
export default function HeaderButton(props : IHeaderBtn) : ReturnBtnComponent {
  const { onClick } = props;

  return (
    <div>{ButtonContents}</div>
  )
}
에러 내용
'Element' 형식은 'ReturnBtnComponent' 형식에 할당할 수 없습니다.
  'ReactElement<any, any>' 형식에서 '(props: IHeaderBtn): ReactElement<any, string | JSXElementConstructor<any>>' 시그니처에 대한 일치하는 항목을 제공하지 않습니다.
'HeaderButton'() JSX 구성 요소로 사용할 수 없습니다.
  해당 반환 형식 'ReturnBtnComponent'() 유효한 JSX 요소가 아닙니다.

왜 이렇게 에러가 발생한 것일까?

바로 함수 표현식과 함수 선언식의 Type 선언 방식을 제대로 알지 못했기 때문이다

함수 선언식과 함수 표현식

다음 식을 보고 기본적으로 어떻게 Type을 선언하는지 익혀두자

함수 선언식

// 함수 선언식
function func(a : number, b : string) : string {
	return `${a, b}`
}

함수 표현식

// 함수 표현식
const func = function(a : number, b : string) : string {
	return `${a, b}`
}

// 화살표 함수 표현식
const func = (a : number, b : string) : string => {
	return `${a, b}`
}

// 함수 표현식에 타입 선언
const func : (x : number, y : string) => string = (a : number, b : string) : string => {
	return `${a, b}`
}

// 함수 표현식에 타입 선언을 할 경우, Argument에선 타입 선언을 생략할 수 있다
const func : (x : number, y : string) => string = (a, b) => {
	return `${a, b}`
}

// Call Signature를 사용하여 더 간결하게 타입을 선언할 수 있다
type funcType = (arg : number, arg2 : string) => string;
const func : funcType => (a, b) => {
	return `${a, b}`
}

💡 함수 타입을 선언할 때 함수 표현식의 타입인지 아니면 ArgumentReturn의 타입인지를 구분해야한다.

위의 내용을 토대로 간단하게 요약해본다면 다음과 같다

// 화살표 함수
const func : (함수 표현식 Type) = (arg : Argument Type) : 함수 Return Type => {
 ...
}

// 일반 함수
function(arg : Argument Type) : 함수 Return Type {
 ...
}

함수 표현식 Type을 선언한다면 함수 표현식 Type에서 모든 타입 체크가 이루어지므로 인자와 반환값의 Type을 굳이 명시해주지 않아도 된다

만약, 함수 표현식 타입이 없다면?

Argument는 어떠한 값이 들어올지 모르기 때문에 에러가 발생하지만 Return타입 추론에 의해 굳이 타입을 선언하지 않아도 타입스크립트 컴파일 단계에서 스스로 판단하여 타입을 넣어준다

function add(a : number, b : number) {
	return a + b;
}

위와 같은 코드를 살펴보면 반환 타입을 명시하지 않아도 타입 추론에 의해 number로 추론된다.

다시 에러 살펴보기

방금 정리했던 내용을 생각하며 다시 에러를 살펴보자.

type ReturnBtnComponent = (props: IHeaderBtn) => React.ReactElement;

export default function HeaderButton(props : IHeaderBtn) : ReturnBtnComponent {
  const { onClick } = props;

  return (
    <div>{ButtonContents}</div>
  )
}

다시 보니 정말 왜 이걸 헷갈렸나 싶을 정도로 단순한 에러였다

ReturnBtnComponent() => void형태의 함수 객체이므로 현재 함수 반환 타입에 맞지 않아 에러가 발생했던 것이다

그렇다면, 올바른 반환 Type을 지정해주면 된다.

type ReturnBtnComponent = (props: IHeaderBtn) => React.ReactElement;

export default function HeaderButton(props : IHeaderBtn) : ReturnType<ReturnBtnComponent> {
  const { onClick } = props;

  return (
    <div>{ButtonContents}</div>
  )
}

ReturnType<T>를 사용하여 ReturnBtnComponent의 반환 Type을 추출하여 해결하였다.

참고

https://inpa.tistory.com/entry/TS-📘-타입스크립트에서-함수-문법-다루기-💯-총정리

함수 - TypeScript Deep Dive (gitbook.io)

#함수#리턴타입#타입스크립트#화살표함수#타입추론