React에서 TypeScript 올바르게 사용하기

Select 컴포넌트를 만든다고 가정해보자.

1
2
3
4
5
6
7
8
9
10
11
12
const Select = ({ label, value, options, onChange }) => {
return (
<label>
{label}
<select value={value} onChange={onChange}>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</select>
</label>
);
};

1. 무지성으로 타입 정의

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Select = ({
label,
value,
options,
onChange,
}: {
label: string;
value: string;
options: { label: string; value: string }[];
onChange: (event: React.ChangeEvent<HTMLSelectElement>) => void;
}) => {
return (
<label>
{label}
<select value={value} onChange={onChange}>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</select>
</label>
);
};

2. type, interface로 타입 정의

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type Option = { label: string; value: string };

type Options = Option[];

type SelectProps = {
label: string;
value: string;
options: Options;
onChange: (event: React.ChangeEvent<HTMLSelectElement>) => void;
};

const Select = ({ label, value, options, onChange }: SelectProps) => {
return (
<label>
{label}
<select value={value} onChange={onChange}>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</select>
</label>
);
};

3. 타입 파일 분리하기

1
2
3
4
5
6
7
8
9
10
11
// Select.d.ts
type Option = { label: string; value: string };

type Options = Option[];

type SelectProps = {
label: string;
value: string;
options: Options;
onChange: (event: React.ChangeEvent<HTMLSelectElement>) => void;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Select.tsx
const Select: React.FC<SelectProps> = ({
label,
value,
options,
onChange,
}): JSX.Element => {
return (
<label>
{label}
<select value={value} onChange={onChange}>
{options.map((option) => (
<option value={option.value}>{option.label}</option>
))}
</select>
</label>
);
};
  • 정답은 없지만 팀 내부에서 하나를 결정하고 통일할 필요는 있다.