bkdragon's log

useReducer Action 객체 타입 본문

React

useReducer Action 객체 타입

bkdragon 2024. 10. 8. 20:42

프로퍼티가 많은 객체를 useReducer를 통해 상태로 다룰 때 Action의 type과 payload를 적절하게 추론하는 타입을 만들어보려고 한다.

목표는 이러하다 예를 들어 아래와 같은 타입이 있다.

type User = {
    email: string;
    password: string;
    name: string;
    phone: string;
    age : number;
    deleted: boolean;
};

이때 Action 객체의 type은 "update_email", "update_password" .... 가 되고 payload가 그거에 맞게 string, string, number, boolean 이 되게 할 것이다.

추후에 상태 업데이트를 위해 dipatch 함수를 사용할 때 타입 추론으로 인해 굉장히 편하게 될 것이다.

type Action<T extends Record<string, any>> = {
    [K in keyof T]: {
        type: `update_${string & K}`;
        payload: T[K];
    };
}[keyof T];

우선 맵드 타입과 탬플릿 리터럴 타입으로 아래와 같이 새로운 형태의 객체를 만든다.

{
    "email" : {
        type : "update_name";
        payload : string;
    };
    "passwor" : {
        type : "update_password";
        payload : string;
    }
    // .... 생략
}

이렇게 만든 상태에서 key로 value를 다시 꺼내주는데 이러면 아래와 같이 union type이 된다.

{
    type : "update_name";
    payload : string;
} |
{
    type : "update_name";
    payload : string;
} |

// .... 생략

이제 type과 payload가 알맞게 추론될 것 이다.

type Data = {
    email: string;
    password: string;
    name: string;
    phone: string;
    age :number;
    deleted: boolean;
};

type Action<T extends Record<string, any>> = {
    [K in keyof T]: {
        type: `update_${string & K}`;
        payload: T[K];
    };
}[keyof T];

type DataAction = Updater<Data>;

IDE 에서 잘 추론되는 것을 볼 수 있다.

dispatch({ type: 'update_email', payload: 'newemail@example.com' });

GOOD!

'React' 카테고리의 다른 글

합성 컴포넌트 패턴과 React Children API 를 활용한 컴포넌트 설계  (0) 2024.10.31
Storybook 으로 협업하기  (1) 2024.10.30
BottomSheet  (0) 2024.10.07
렌더링과 커밋  (2) 2024.09.21
[React Query] 쿼리 키 관리하기  (0) 2024.07.16