React + TypeScript
HTML Props
情境: 預期 Button
有原生 html button props 的 autocomplete
const Parent = () => {
return <Button onClick={() => {}} type="button"></Button>;
};
✅
export const Button = ({ className, ...rest }: React.ComponentProps<'button'>) => {
return <button {...rest} className={className}></button>;
};
覆蓋原生 Props
情境: 預期 Input
的 onChange
props 參數為 string
export const Input = (props: InputProps) => {
return (
<input
{...props}
onChange={(e) => {
props.onChange(e.target.value);
}}
/>
);
};
const Parent = () => {
return (
<Input
onChange={(val) => {
// val: string
console.log(val);
}}
/>
);
};
❌ val: string
or React.ChangeEvent<HTMLInputElement>
.
type InputProps = ComponentProps<'input'> & { onChange: (value: string) => void };
✅
type InputProps = Omit<ComponentProps<'input'>, 'onChange'> & { onChange: (value: string) => void };
提取元件 Props
情境: NavBar
是第三方的元件,如果要使用 NavBar
的 props,但第三方並未將其 props export 出來。
type NavBarProps = { title: string; links: string[]; children: React.ReactNode };
export const NavBar = (props: NavBarProps) => {
return <div>Some content</div>;
};
✅
type NavBarProps = React.ComponentProps<typeof NavBar>;
使用 useState
update function 更新狀態
情境: setState
function 回傳的物件,有額外的 tagselected 屬性,但 typescript 並未報錯。
type TagState = {
tagSelected: number | null;
tags: { id: number; value: string }[];
};
export const Tags = () => {
const [state, setState] = useState<TagState>({
tags: [],
tagSelected: null,
});
return (
<div>
{state.tags.map((tag) => {
return (
<button
key={tag.id}
onClick={() => {
setState((currentState) => ({
...currentState,
// @ts-expect-error
tagselected: tag.id,
}));
}}
>
{tag.value}
</button>
);
})}
</div>
);
};
✅ 在 TypeScript 中,可以從函式回傳值中傳遞額外的属性。一般而言,在使用 TypeScript 時,應該盡量進行物件比較,因為這樣可以提供更好的錯誤訊息。
<button
key={tag.id}
onClick={() => {
setState(
(currentState): TagState => ({
...currentState,
tagselected: tag.id,
}),
);
}}
>
{tag.value}
</button>
參考來源: