배열을 반환할 때 React TypeScript Hooks 문제

Read in light, dark or sepia mode on my blog



React와 TypeScript는 의미 있는 쌍을 이룹니다. 결합하면 전 세계를 함께 지배할 수 있습니다. 하지만 때때로 이 두 사람은 몇 가지 작은 세부 사항에 대해 접점을 찾을 수 있으며, 우리 개발자는 자존심 싸움에서 희생양이 되어야 합니다. 이러한 문제 중 하나는 useState 와 같이 값과 함수의 배열을 반환하는 자체 사용자 지정 후크를 만들 때입니다.

const [state, setState] = useState(null);

state가 값이고 setState가 함수라는 것이 명확하게 보입니다. 이 후크를 사용하면 모든 것이 잘 작동하고 이 2개에는 고유한 유형이 있습니다.

그러나 useState 와 구조가 매우 유사한 배열을 반환하는 고유한 후크를 만들려고 할 때 문제가 발생합니다. 예를 보자:

import { useState } from 'react';

export function useTheme() {
  const [theme, setTheme] = useState('light');

  // Do epic stuff here

  // Return the 2 state variables
  return [theme, setTheme];
}


여기에 테마 전환 마법을 관리하는 useTheme 후크가 있습니다. 여기에서 상태 변수 theme 를 setter useTheme 와 함께 선언합니다. 그런 다음 이 두 변수를 사용하여 웹 개발 쿵푸를 수행합니다. 마지막으로 [theme, setTheme] 의 배열을 반환하므로 테마를 활용하고 어디서나 변경할 수 있습니다. 괜찮아.

이 후크를 사용하려고 할 때까지 😈

테마를 전환하는 작업을 하는 구성 요소를 작성 중이고 이를 위해 우리의 useTheme 후크를 사용한다고 가정해 보겠습니다.

이 후크에서 내보낸 setTheme를 사용하여 테마를 변경하는 함수를 만듭니다.

const [theme, setTheme] = useTheme();

const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');


이상한 오류가 발생합니다.



TypeScript에 따른 오류는 다음과 같습니다.

This expression is not callable.
Not all constituents of type 'string | Dispatch<SetStateAction<string>>' are callable.
Type 'string' has no call signatures.ts(2349)


이상 하네. 왜 그런 일이 발생합니까?

(TLDR) 솔루션



설명을 시작하기 전에 여기에 최종 솔루션이 있습니다.

옵션 1



이 함수의 반환 유형을 Tuple로 만듭니다(설명은 아래 섹션 참조).

import { useState, useEffect } from 'react';

type TTheme = 'light' | 'dark';

export function useTheme(): [string, React.Dispatch<React.SetStateAction<string>>] {
...


이것은 배열 대신 튜플을 반환하므로 모든 요소는 고유한 별도의 유형을 갖습니다. 오류가 해결됩니다

옵션 2



이것은 덜 장황한 방법이며 첫 번째 방법보다 이 방법을 선호합니다.

import { useState, useEffect } from 'react';

type TTheme = 'light' | 'dark';

export function useTheme() {
  ...

  return [theme, setTheme] as const;
}

as const 이상하게 보일 수 있지만 완벽하게 유효합니다. 이 경우 TypeScript가 반환되는 배열을 튜플readonly로 유추하게 합니다. 이것은 완벽하게 작동합니다.

설명



자세히 보면 여기서 setTheme의 유형은 다음과 같이 표시됩니다.

string | React.Dispatch<React.SetStateAction<string>>


하지만 이상합니다. 우리는 setTheme가 함수라는 것을 분명히 알고 있습니다. 편집기에서 마우스를 가져가면 유형이 React.Dispatch<React.SetStateAction<string>> 이고 구성 요소로 string 유형이 없음을 확인할 수 있습니다.

하지만 그게 다가 아닙니다. theme 위에 마우스를 올려 놓으면 위의 setState와 동일한 유형입니다.

그리고 useTheme 위로 마우스를 가져가면 위 👇 유형의 배열을 반환한다는 것을 알 수 있습니다.

(string | React.Dispatch<React.SetStateAction<string>>)[]




이상하다. TypeScript가 각 항목의 유형을 어떻게 구분하게 할 수 있습니까?

여기에 대답은 튜플입니다.

TypeScript의 튜플



튜플은 배열과 똑같이 생겼습니다. 다음은 배열입니다.

[2, 'hello', true];


다음은 튜플입니다.

[2, 'hello', true];


둘의 차이점은? TypeScript에서 추론한 첫 번째 유형은 (number | string | boolean)[] 이고 두 번째 유형 추론은 [number, string, boolean] 입니다. Array 예제에서 TypeScript는 모든 단일 항목에 동일한 유형을 할당합니다. 기술적으로 이것이 Array의 정의이기 때문입니다.

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.



모두 같은 종류입니다. 그렇기 때문에 TypeScript는 공용체 유형 연산자(|)를 사용하여 배열 요소에서 가능한 모든 유형을 결합하여 모든 단일 요소에 동일한 유형을 할당합니다.

반면에 튜플은 주문 쌍입니다. 즉, 유형을 정의하는 순서대로 튜플에 입력하는 순서입니다. 따라서 TypeScript는 배열 인덱스를 기반으로 올바르게 추론합니다.

튜플 유형 정의



이것은 간단합니다. 나타나는 순서대로 유형을 지정하기만 하면 됩니다.

const coordinates: [number, number] = [23.4, 43.67];


간단합니다 :)

결론



그래서 이것이 이 글의 끝입니다. 당신이 그것에서 좋은 것을 얻었기를 바랍니다.

종료합니다.

좋은 웹페이지 즐겨찾기