본문으로 바로가기

다음과 같이 열고 닫음을 처리하는 커스텀 훅이 존재한다고 가정하자.

import { useState, useCallback } from 'react'

const useToggle = (initialState: boolean) => {
  const [state, setState] = useState(initialState)
  const toggle = useCallback(() => {
    setState((state) => !state)
  }, [])

  const open = useCallback(() => setState(true), [])
  const close = useCallback(() => setState(false), [])

  return [state, open, close, toggle]
}

export default useToggle

 

위와 같은 코드에서 [state, open, close, toggle]이 추론되는 걸로는 (boolean | (() => void))[] 과 같이 추론된다.

즉, 저 배열이 boolean 혹은 () => void 꼴의 함수를 원소로 가진 지닌 Array로 인식하는 것이다.

따라서 저 커스텀 훅을 사용하는 곳에서 아래와 같이 타이핑이 들어간다.

const [showDocuments, , , ] = useToggle(hasCurrentDocument

<OtherLibraryProject
  showDocuments={showDocuments} // boolean이 아닌 boolean | (() => void) 라고 추론됨
  ...props 
/>

 

이를 해결하기 위해서는 튜플을 사용하면 된다.

튜플은 Array와 다르게 길이를 알고 있고 각 요소의 유형들을 알고 있어 의도한대로 타입 추론이 되므로 튜플로 반환해주면 된다.

가장 빠른 건 const assertion이다.

const useToggle = (initialState: boolean) => {
  // ...omitted
  
  return [state, open, close, toggle] as const
}

이제 이렇게 올바르게 추론된다. readonly [boolean, () => void, () => void, () => void]

 

as const가 아닌 직접 타이핑을 줌으로써 튜플을 반환하고 싶다면 그렇게 해도 된다.

type useToggleReturnType = [boolean, () => void, () => void, () => void]

const useToggle = (initialState: boolean): useToggleReturnType => {
  // ...omitted

  return [state, open, close, toggle]
}

 

Tuple

https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types

 

Documentation - Object Types

How TypeScript describes the shapes of JavaScript objects.

www.typescriptlang.org

 

 

 

as const를 왜 씀?

tuple을 정의하기 위해서는 1) tuple typing을 해주거나 2) const assertion을 하면 된다.

 

as const에 대해서 조금 살펴보자면, javascript에서 배열이나 객체는 const로 선언하더라도 내부 값을 변환시킬 수 있었으나, as const로 const assertion을 하게 되면 readonly가 붙어 내부 변환을 할 수 있다. 즉 정말로 말그대로 '상수'처럼 취급되는 것이다. 

const a = [1, 2, 3];
a[2] = 100;

const b = [1, 2, 3] as const; // readonly [1, 2, 3]
b[2] = 100; // Cannot assign to '2' because it is a read-only property.

 

좀 더 자세한 내용은 아래를 참고하자.

https://darrengwon.tistory.com/1130?category=867626 

 

literal type과 const assertion

literal type literal type은 간단히, 특정 값을 타입으로 고정시키는 것이다. 물론 특정 값을 type 선언해서 사용할 수도 있긴 하다. deprecated라고 뜰 뿐이지... type name = 'Darren' const me: 'Darren' = 'D..

darrengwon.tistory.com

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체