아래와 같은 타입이 있다고 가정
export type OrderStatus = 'pending' | 'new' | '...생략'
export type Client = { user_id: number; company_name: string; };
export type OrderFilterParams = {
status: Array<OrderStatus>;
client: Array<Client>;
// ...생략
};
ClientAndOrderFilter
컴포넌트에선 "status" | "client"
두 종류의 타입을 받아 params[type]
형태로 OrderFilterParams
객체에 접근해서 값을 변경해야 하는 상황
interface ClientAndOrderFilterProps {
setParams: Dispatch<SetStateAction<OrderFilterParams>>;
params: OrderFilterParams;
type: "status" | "client"
// ...
}
하지만 ClientAndOrderFilter
컴포넌트에서 어떤 종류의 type
("status" | "client"
)을 받을지 타입스크립트는 알 수 없기 때문에 params[type]
형태로 접근하면 타입 추론이 이뤄지지 않아 에러 발생
아래처럼 식별자 영역에선 type
("status" | "client"
) Prop 타입으로 T
의 제약 조건을 지정하고, 구현부에선 T
타입에 따라 다른 값을 반환하는 조건부 타입(OrderStatus[] | Client[]
)을 사용하면 문제를 해결할 수 있음
// 변경 전 (각 key에 할당될 값을 고정하지 않았으므로 수정 필요)
export type OrderFilterParams = { [key in OrderFilterType]?: Array<OrderStatus | ISODateString | ClinicLabType> };
// 변경 후
export type OrderFilterParams = {
status: Array<OrderStatus>;
client: Array<Client>;
startdate: Array<ISODateString>;
enddate: Array<ISODateString>;
};
export type ListType = "status" | "client";
// OrderStatus[] / Client[] 2가지 종류의 배열을 받으므로 제네릭 사용해서 타입 가드
// <T = ListType> 부분은 타입 식별자. "status" | "client"를 T의 기본값으로 지정
// Array<T extends ...> 부분은 타입 구현부. T를 "status"로 받으면 OrderStatus[] 타입을 리턴하고 그 외엔 Client[] 타입 리턴
export type ListFilter<T = ListType> = Array<T extends "status" ? OrderStatus : Client>;
이제 params[type]
의 타입을 ListFilter<typeof type>
으로 지정하면 타입 에러 해결됨 ✨
const clickHandler = (status: ListFilterStatus) => {
setParams((prevParams) => {
const params: ListFilter<typeof type> = prevParams[type];
// ...
return {
...prevParams,
[type]: params.filter(param => /* ... */)
};
});
};