티스토리 뷰

Redux 공식 문서를 봐가면서 Redux를 적용했는데 reducer함수의 action 타입을 정해주는데 애를 먹었다. 이를 해결하다가 새로운 타입스크립트 문법을 알게 되었다.

// action의 타입을 무엇으로 해야한단말인가...
const todoReducers = (state = initialState, action) => {
  switch (action.type) {
  	case 'ADD_TODO': 
    // ... state 변경 로직
  }
}

 

ReturnType

ReturnType을 사용하면 함수 Type의 반환 타입으로 구성된 타입을 생성한다.

ReturnType<Type>
// 예시
type T0 = ReturnType<() => string>;
 //  type T0 = string
     
type T1 = ReturnType<(s: string) => void>;
 //  type T1 = void
     
type T2 = ReturnType<<T>() => T>;
  // type T2 = unknown
     
type T3 = ReturnType<<T extends U, U extends number[]>() => T>;
   // type T3 = number[]

declare function f1(): { a: number; b: string };
type T4 = ReturnType<typeof f1>;
   // type T4 = {
   //  a: number;
   //  b: string;
   // }
 
type T5 = ReturnType<any>;
  // type T5 = any
     
type T6 = ReturnType<never>;
  // type T6 = never
     
type T7 = ReturnType<string>;
//Type 'string' does not satisfy the constraint '(...args: any) => any'.
  // type T7 = any
    
type T8 = ReturnType<Function>;
// Type 'Function' does not satisfy the constraint '(...args: any) => any'.
// Type 'Function' provides no match for the signature '(...args: any): any'.
  // type T8 = any

 

any로 되어있는 aciton의 타입을 설정해 줄 때 ReturnType을 활용할 수 있다.

 

as const (const assertion)

addTodo라는 action 함수를 기존에 이렇게 해두었는데 이 상태로 ReturnType을 사용하게 되면 type(key)의 값의 타입(type : string)이 string으로 들어가게 된다.

export const addTodo = (input: string) => {
  return {
    type: 'ADD_TODO',
    input,
  };
};
export type TodoActionType = ReturnType<typeof addTodo>

// const addTodo: (input: string) => {
//    type: string;
//    input: string;
// }

 

그래서 addTodo가 리턴하는 객체의 type(key)의 값의 타입(type : 'ADD_TODO')으로 'ADD_TODO' 문자열이 추론되도록 하기 위해서 변수로 선언하고 as const를 붙여준다. 그럼 ReturnType의 addTodo에서 리턴되는 객체의 type의 값의 타입이 "ADD_TODO"로 고정된다.

const ADD_TODO = 'ADD_TODO' as const;

export const addTodo = (input: string) => {
  return {
    type: ADD_TODO,
    input,
  };
};
export type TodoActionType = ReturnType<typeof addTodo>

// const addTodo: (input: string) => {
//    type: "ADD_TODO";
//    input: string;
// }

 

그리고 다른 액션 함수들에도 같은 방식을 적용해주고 reducer 함수의 action 타입을 정해주면 더 이상 action은 any가 아니게 된다.

const ADD_TODO = 'ADD_TODO' as const;
const EDIT_MODE = 'EDIT_MODE' as const;
const EDIT_TODO = 'EDIT_TODO' as const;
const DELETE_TODO = 'DELETE_TODO' as const;
const CHECK_TODO = 'CHECK_TODO' as const;

export type TodoActionType =
  | ReturnType<typeof addTodo>
  | ReturnType<typeof goEditMode>
  | ReturnType<typeof editTodo>
  | ReturnType<typeof deleteTodo>
  | ReturnType<typeof checkTodo>;
  
export const addTodo = (input: string) => {
  return {
    type: ADD_TODO,
    input,
  };
};

// ... 그리고 남은 액션 함수들
import { TodoActionType } from '../actions/todoActions';

// action에게도 타입이 생겼어요!
const todoReducers = (state = initialState, action: TodoActionType) => {
  switch (action.type) {
    case 'ADD_TODO': 
    // ... state 변경 로직
  }
}
728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함