TypeScript中如何约束Select组件的defaultValue为options的可选值
实现方案
核心思路是通过泛型自动推断传入的options数组的value类型,将defaultValue的类型约束为所有options的value组成的字面量联合类型,即可实现非法值的类型报错。
第一步:定义泛型Props和组件
import type { ReactNode } from 'react' // 定义Option的基础类型约束,可根据业务需求扩展value支持的类型 type OptionBase = { value: string | number | boolean label: ReactNode } // Select组件的泛型Props type SelectProps<T extends OptionBase> = { // 加readonly兼容as const生成的只读数组类型 options: readonly T[] defaultValue: T['value'] // 其他业务需要的Props可以在这里追加,示例: onChange?: (value: T['value']) => void placeholder?: string } // 泛型Select组件实现 function Select<T extends OptionBase>(props: SelectProps<T>) { // 组件内部逻辑省略 return <select>{/* 渲染逻辑 */}</select> } // 如果你习惯用箭头函数写法,直接这么写就行,不需要套React.FC(React.FC不支持直接传递泛型) const SelectArrow = <T extends OptionBase>(props: SelectProps<T>) => { return <select>{/* 渲染逻辑 */}</select> }
第二步:使用测试
和你给出的示例用法完全匹配:
const countryOptions = [ { value: "au", label: "Australia", }, { value: "nz", label: "New Zealand", } ] as const; // ✅ 合法写法,无类型报错 <Select options={countryOptions} defaultValue="au" /> // ❌ 触发类型报错:类型"foo"不能分配给类型"au" | "nz" <Select options={countryOptions} defaultValue="foo" />
注意事项
如果不使用
as const声明options数组,TS会默认把value的类型推断为通用的string而非"au" | "nz"这类字面量联合类型,就不会触发非法defaultValue的类型校验,所以要实现这个效果必须给options加上as const声明。
内容的提问来源于stack exchange,提问作者Misha Moroshko
相关产品推荐
相关产品推荐

