我正在使用 Typescript 在 React 中创建 Select 组件。这是代码:
type GenericSelectProps = {
values: (Book | Movie)[];
onChange: (value: Book | Movie) => void;
};
export const GenericSelect = ({ values, onChange }: GenericSelectProps) => {
const onSelectChange = (e) => {
const val = values.find((value) => value.id === e.target.value);
if (val) onChange(val);
};
return (
<select onChange={onSelectChange}>
{values.map((value) => (
<option key={value.id} value={value.id}>
{value.title}
</option>
))}
</select>
);
};
export type Book = {
id: string;
title: string;
author: string;
};
export type Movie = {
id: string;
title: string;
releaseDate: string;
};
const books: Book[] = [
{
id: "1",
title: "Good omens",
author: "Terry Pratchett & Neil Gaiman"
},
{
id: "2",
title: "The Truth",
author: "Terry Pratchett"
}
];
当我尝试使用这样的组件时:
<GenericSelect
onChange={(value) => console.log(value.author)}
values={books}
/>
然后打字稿显示错误,因为它与值混淆,即它是电影还是书籍。但是,如果我们使用类型缩小,那么无论如何都不起作用。
<GenericSelect
onChange={(value) => {
if ("author" in value) {
console.log(value.author); // Only accessible if `value` is a `Book`
} else {
console.log(value.title); // Only accessible if `value` is a `Movie`
}
}}
values={books}
/>
使用类型保护对你有用吗?
function isBook(obj: unknown): obj is Book {
return obj?.author !== undefined
}
您可以像这样在代码中使用它:
<GenericSelect
onChange={(value) => {
if (isBook(value)) {
console.log(value.author); // Only accessible if `value` is a `Book`
} else {
console.log(value.title); // Only accessible if `value` is a `Movie`
}
}}
values={books}
/>