아래와 같이 공통 컴포넌트에서 onSelect의 param을 any로 정의하는 것에 대한 문제를 해결하고 싶었다.
// SelectField.tsx (공통 컴포넌트)
interface Props {
...
onSelect?: (param: any) => void;
}
const SelectField = (props: Props) => {
return(
<Select onSelect={onSelect} />
)
}
첫번째 방법 (Not OK)
- onSelect의 제네릭 타입을 param에 넘겨주는 방법을 시도 했다.
- 에러는 없으나 Form.tsx에서 제네릭이 any로 추론되어 적용되었기 때문에 올바른 방법이 아니다.
- 또한 onSelectSettlementPeriodType라는 함수를 실행할때에는 타입을 넣어주어서 의미가 있겠지만 props로 넘겨만 주고 실행은 antd에서 알아서 하기 때문에 이렇게 제네릭을 사용할 필요는 없었다.
// SelectField.tsx
interface Props {
...
onSelect?: <T,>(param: <T>) => void;
}
const SelectField = (props: Props) => {
return(
<Select onSelect={onSelect} />
)
}
// Form.tsx
const onSelectSettlementPeriodType = <SettlementPeriodType,>(selectedValue?: SettlementPeriodType) => {
if (selectedValue === "SettlementPeriodType이 아닌 값") {
// 에러 발생하지 않는다.
// selectedValue가 any로 추론되기 때문에 선언부만 필요한 함수의 경우 의미가 없는 제네릭이다.
// selectedValue에 뭐를 넣어도 타입 에러가 발생하지 않는다.
// SettlementPeriodType를 T로 바꿔서 넣은 것도 마찬가지인데 착각을 함
}
};
return(
<SelectField
onSelect={onSelectMarketingExpenseSettlementType}
/>
)
두번째 방법 (OK)
- 제네릭 인터페이스 적용
- Form.tsx에서 MarketingExpenseSettlementType을 제네릭으로 넘겨주고 SelectField.tsx의 Props interface에서 onSelect의 param 타입으로 받아온 제네릭을 넘겨서 타입을 정의했다.
- 이렇게 하면 onSelectMarketingExpenseSettlementType 함수 선언부에서 MarketingExpenseSettlementType만 param으로 받아오게 강제하기 때문에 제네릭을 사용한 효과가 있다.
// SelectField.tsx
interface Props<T> {
onSelect?: (param: T) => void;
}
const SelectField = <T,>(props: Props<T>) => {
return(
<Select onSelect={onSelect} />
)
}
// Form.tsx
...
const onSelectSettlementPeriodType = (selectedValue?: SettlementPeriodType) => {
if (selectedValue === "SettlementPeriodType가 아닌 타입") {
// MarketingExpenseSettlementType이 아니기 때문에 에러 발생
// 제네릭으로 넘겨준 타입이 잘 동작하였다!
}
};
return(
<SelectField<MarketingExpenseSettlementType> // 이렇게 제네릭을 넘겨줄 수 있다.
onSelect={onSelectMarketingExpenseSettlementType}
/>
)
세번째 방법 (OK)
- antd의 SelectProps에게 타입을 맡기고 onSelect의 타입을 정의 하지 않는다.
- SelectProps 내부에 onSelect의 타입이 정의가 되어있다.
- 하지만 내부에서 onSelect의 param은 any로 되어 있음을 참고해야 한다.
// SelectField.tsx
import { Select, SelectProps } from 'antd';
interface Props {
...
// onSelect의 타입을 따로 정의하지 않고 antd SelectProps에 맡김
}
type SelectFieldProps = Props & SelectProps;
const SelectField = (props: SelectFieldProps) => {
return(
<Select onSelect={onSelect} ... />
)
}
요약
- 공통 컴포넌트에서 명시적으로 제네릭을 활용하여 props의 타입정의를 하고 싶으면 두번째 방법을 사용하면 어떨까 알아 보았다. 더 좋은 방법이 있을 수도 있다.
- 라이브러리에서 미리 제공하는 타입이 있다면 사용해도 된다. 내부적으로는 어떤 타입인지를 알고 있으면 될 것 같다.
헷갈렸던 부분
- onSelect가 제네릭으로 타입 정의되어 있더라도 별도로 실행을 시키는 곳은 없다. 즉 함수 실행과 동시에 타입을 제네릭으로 넣어주는 부분도 없기 때문에 onSelect함수를 꼭 제네릭으로 선언하여 props로 넘겨줄 필요가 없었다.
'React.JS' 카테고리의 다른 글
react-hook-form onBlur 안될때 (0) | 2022.09.28 |
---|---|
Prop `className` did not match (0) | 2022.01.18 |
React.js와 Codeigniter 연결하기 (0) | 2021.04.26 |
hooks로 componentWillUnmount 구현하기 (0) | 2021.04.14 |
react직접 만들어 보기(2) _ render 메서드 구현 (0) | 2021.01.02 |