Reactjs 反应+;Typescript:使用具有可选泛型类型函数的道具正确键入通用组件
我曾经(现在仍然)在措辞上有困难,如果这个问题很难理解,我很抱歉 问题:Reactjs 反应+;Typescript:使用具有可选泛型类型函数的道具正确键入通用组件,reactjs,typescript,Reactjs,Typescript,我曾经(现在仍然)在措辞上有困难,如果这个问题很难理解,我很抱歉 问题: 如何使用具有可选通用类型函数的道具正确键入通用组件, 这样我就可以创建使用和不使用可选泛型类型的组件了 例如(也可以在codesandbox中查看代码): 代码沙盒: 假设我想要一个包含1个基本搜索字段和可选搜索字段的搜索表单。 此外,可选的搜索字段根据使用方式返回不同但特定类型的数据。 我们事先知道具体的类型,所以我们将它们称为A和B 因此,我决定创建以下通用组件名称Search: // the specific typ
如何使用具有可选通用类型函数的道具正确键入通用组件,
这样我就可以创建使用和不使用可选泛型类型的组件了 例如(也可以在codesandbox中查看代码):
代码沙盒: 假设我想要一个包含1个基本搜索字段和可选搜索字段的搜索表单。 此外,可选的搜索字段根据使用方式返回不同但特定类型的数据。 我们事先知道具体的类型,所以我们将它们称为
A
和B
因此,我决定创建以下通用组件名称Search
:
// the specific types of data that the optional search field(s) return
export type OptionalSearchTypeA = {
keyA1: string
keyA2: string
}
export type OptionalSearchTypeB = {
keyB1: string
}
// a union type of all types of optional search field(s) to restrict the type in generics
// allow undefined since it is optional
export type OptionalSearchType = OptionalSearchTypeA | OptionalSearchTypeB | undefined
// the search state used in the search component
export type SearchStateType<T extends OptionalSearchType = undefined> = {
search: string
optionalSearch?: T
}
// props for the actual search component
export type SearchProps<T extends OptionalSearchType = undefined> = {
label: string
searchState: SearchStateType<T>
onChange: (searchState: SearchStateType<T>) => void
hasOptionalSearch: boolean
}
// actual Search component
export const Search = <T extends OptionalSearchType = undefined>({
label,
searchState,
onChange,
hasOptionalSearch,
}: SearchProps<T>) => {
const handleChangeSearch = (e: ChangeEvent<HTMLInputElement>) => onChange({ ...searchState, search: e.target.value })
return (
<label id={label}>
<div>{label}</div>
<input id={label} value={searchState.search} onChange={handleChangeSearch} />
{/* hasOptionalSearch && (generate optional input field based on searchState.optionalSearch) */}
</label>
)
}
现在当我在应用程序中使用它时…我得到一个错误
// searchState for components for both specific type and with optional and without optional
export const A_initSearchStateWithOptional: SearchStateType<OptionalSearchTypeA> = {
search: '',
optionalSearch: {
keyA1: '',
keyA2: '',
},
}
export const A_initSearchStateWithoutOptional: SearchStateType = {
search: '',
}
export const B_initSearchStateWithOptional: SearchStateType<OptionalSearchTypeB> = {
search: '',
optionalSearch: {
keyB1: '',
},
}
export const B_initSearchStateWithoutOptional: SearchStateType = {
search: '',
}
export const App = () => {
const [A_searchStateWithOptional, setA_searchStateWithOptional] = useState(A_initSearchStateWithOptional)
const [A_searchStateWithoutOptional, setA_searchStateWithoutOptional] = useState(A_initSearchStateWithoutOptional)
const [B_searchStateWithOptional, setB_searchStateWithOptional] = useState(B_initSearchStateWithOptional)
const [B_searchStateWithoutOptional, setB_searchStateWithoutOptional] = useState(B_initSearchStateWithoutOptional)
// typescript tells me that onChange has a type mismatch, but I know that it will return the type I expect
return (
<div className="App">
<SearchA
label="Search A with Optional"
searchState={A_searchStateWithOptional}
onChange={setA_searchStateWithOptional}
hasOptionalSearch={true}
/>
<SearchA
label="Search A without Optional"
searchState={A_searchStateWithoutOptional}
onChange={setA_searchStateWithoutOptional}
hasOptionalSearch={false}
/>
<SearchB
label="Search B with Optional"
searchState={B_searchStateWithOptional}
onChange={setB_searchStateWithOptional}
hasOptionalSearch={true}
/>
<SearchB
label="Search B without Optional"
searchState={B_searchStateWithoutOptional}
onChange={setB_searchStateWithoutOptional}
hasOptionalSearch={false}
/>
</div>
)
}
//搜索特定类型和带可选和不带可选组件的组件的状态
导出常量A_initSearchStateWithOptional:SearchStateType={
搜索:“”,
可选搜索:{
关键字A1:“”,
关键字A2:“”,
},
}
导出常量A_initSearchStateWithout可选:SearchStateType={
搜索:“”,
}
导出常量B_initSearchStateWith可选:SearchStateType={
搜索:“”,
可选搜索:{
键B1:“”,
},
}
导出常量B_initSearchStateWithout可选:SearchStateType={
搜索:“”,
}
导出常量应用=()=>{
const[A_searchStateWithOptional,setA_searchStateWithOptional]=useState(A_initSearchStateWithOptional)
const[A_searchStateWithoutOptional,setA_searchStateWithoutOptional]=useState(A_initSearchStateWithoutOptional)
const[B_searchStateWithOptional,setB_searchStateWithOptional]=useState(B_initSearchStateWithOptional)
const[B_searchstate without optional,setB_searchstate without optional]=使用状态(B_initsearchstate without optional)
//typescript告诉我onChange有一个类型不匹配,但我知道它将返回我期望的类型
返回(
)
}
错误如下:
Type 'Dispatch<SetStateAction<SearchStateType<OptionalSearchTypeA>>>' is not assignable to type '(searchState: SearchStateType<OptionalSearchTypeA | undefined>) => void'.
Types of parameters 'value' and 'searchState' are incompatible.
Type 'SearchStateType<OptionalSearchTypeA | undefined>' is not assignable to type 'SetStateAction<SearchStateType<OptionalSearchTypeA>>'.
Type 'SearchStateType<OptionalSearchTypeA | undefined>' is not assignable to type 'SearchStateType<OptionalSearchTypeA>'.
Type 'OptionalSearchTypeA | undefined' is not assignable to type 'OptionalSearchTypeA'.
Type 'undefined' is not assignable to type 'OptionalSearchTypeA'.ts(2322)
index.ts(6, 3): The expected type comes from property 'onChange' which is declared here on type 'IntrinsicAttributes & SearchAProps'
Type'Dispatch'不可分配给Type'(searchState:SearchStateType)=>void'。
参数“value”和“searchState”的类型不兼容。
类型“SearchStateType”不可分配给类型“SetStateAction”。
类型“SearchStateType”不可分配给类型“SearchStateType”。
类型“OptionalSearchTypeA |未定义”不可分配给类型“OptionalSearchTypeA”。
类型“未定义”不可分配给类型“OptionalSearchTypeA”。ts(2322)
ts(6,3):预期的类型来自属性“onChange”,该属性在类型“IntrinsicAttributes&SearchAProps”上声明
它告诉我不能将OptionalSearchType*| undefined
分配给OptionalSearchType*
我知道对于带有
haoptionalsearch={true}
的搜索组件,我将收到OptionalSeachType*
,而对于带有haoptionalsearch={false}
的组件,我知道它将是未定义的。我必须仍然使用useState
键入它们吗?我只想简单地说它是useState
或useState
,因为我知道这就是将返回的内容。通过将类型提供给useState,您应该能够使onChange函数比TS推断的更不具体
useState(A_initSearchStateWithOptional)
你要找的可能是有区别的工会类型
type SearchTypes = {
hasOptional: true;
optionalSearh: {
type: string;
};
} | {
hasOptional: false;
};
使用此类型将告诉typescript,当hasOptional=true时,对象上必须存在optionalSearch字段。感谢您的回复!而您的答案确实解决了类型错误。我不得不重新措辞我的问题,因为它没有提出我想问的问题。抱歉,我知道我将收到带有hasOptionalSearch={true}
的组件的OptionalSeachType*
,而对于带有hasOptionalSearch={false}
的组件,它将是未定义的。我必须仍然使用useState
键入它们吗?我只想简单地说它是useState`或者useState
,因为我知道它将被返回。我仍在努力理解这个任务。补充了另一个答案。
type SearchTypes = {
hasOptional: true;
optionalSearh: {
type: string;
};
} | {
hasOptional: false;
};