ISSUE
// 단순 예시입니다.
import { useState } from "react";
const useToast = () => {
const [isOpen, setIsOpen] = useState(false);
const handleToast = () => {
setIsOpen((prev) => !prev);
};
return [isOpen, handleToast];
};
export default useToast;
// error
// const handleToast: boolean | (() => void)
// This expression is not callable.
// Not all constituents of type 'boolean | (() => void)' are callable.
// Type 'false' has no call signatures.ts(2349)
위와 같이, 튜플 타입의 배열을 리턴하는 커스텀훅에서 handleToast
를 사용하던 도중 타입 에러가 발생하였다. 확인해보니, TS의 배열 타입 추론으로 인해 발생한 에러였다. 일반적으로 배열의 정의는 다음과 같다.
An array is a data structure that contains a group of elements. Typically these elements are all of the same data type, such as an integer or string.
정의에서 말하는 것처럼, 배열은 일반적으로 같은 데이터 타입을 가진 요소들의 집합이다. 때문에 TS에서는, 배열 내부 요소들에게 같은 타입을 부여하게 되므로 위의 예시에서처럼 우리가 원했던 리턴 값의 타입이 [boolean, () => void]
가 아닌, (boolean | (() => void))[]
로 추론되었다. 타입이 광범위하게 추론이 된 것이다. 때문에 이를 해결하기 위해서는, 해당 함수의 리턴 타입을 직접 지정해주거나 as const
를 통해 const assertion
를 사용함으로써 타입 추론의 범위를 좁혀줄 수 있다.
// readonly [boolean, () => void];
[isOpen, handleToast] as const;
const assertion with as const
const assertion
은, TS 3.4에 추가된 기능으로, 다음과 같은 타입과 같은 효과가 있다.
- 해당 리터럴의 타입 확장 X
- 객체의 경우, 속성값들에게
readonly
부여 - 배열의 경우,
readonly
가 부여된 튜플 타입으로 변경
// Type '"hello"'
let x = "hello" as const;
// Type 'readonly [10, 20]'
let y = [10, 20] as const;
// Type '{ readonly text: "hello" }'
let z = { text: "hello" } as const;
.tsx
형식의 파일 외부에서는, 다음과 같이 사용될 수도 있다.
// Type '"hello"'
let x = <const>"hello";
// Type 'readonly [10, 20]'
let y = <const>[10, 20];
// Type '{ readonly text: "hello" }'
let z = <const>{ text: "hello" };
추가로, enum
구조를 사용하지 않는다면, const assertion
을 통해 대신 사용할 수도 있다.
export const Colors = {
red: "RED",
blue: "BLUE",
green: "GREEN",
} as const;
Reference
'TypeScript' 카테고리의 다른 글
TIL | Type guard (0) | 2022.03.15 |
---|---|
TIL | Index signature (0) | 2021.10.24 |
TIL | Interface VS Type (0) | 2021.10.24 |
TIL | Generics (0) | 2021.10.23 |
TIL | Interface (0) | 2021.10.23 |