对不起,我不知道确切的名字。
使用react和typescript: 我有一个组件,它根据我作为道具传递的类型来创建一个组件集:
interface FieldDispatcherProps {
children: Array<never>;
fieldId: string;
mandatory?: boolean;
mode: FieldMode;
onChange: Function;
}
const fieldTypes = {
[FieldsHelper.fields.text.value] : TextField,
[FieldsHelper.fields.textarea.value] : TextAreaField,
[FieldsHelper.fields.select.value] : SelectField,
[FieldsHelper.fields.radio.value] : RadioField,
[FieldsHelper.fields.checkbox.value] : CheckboxField,
[FieldsHelper.fields.autonum.value] : AutonumField,
[FieldsHelper.fields.number.value] : NumberField,
[FieldsHelper.fields.file.value] : FileField,
[FieldsHelper.fields.calc.value] : CalcField,
[FieldsHelper.fields.user.value] : UserField,
[FieldsHelper.fields.dslookup.value] : LookupField,
[FieldsHelper.fields.date.value] : DateField,
[FieldsHelper.fields.time.value] : TimeField,
}
const FieldDispatcher = (props: FieldDispatcherProps): JSX.Element => {
const {fieldId, mandatory, mode, onChange}: FieldDispatcherProps = props;
const field = useSelector((state: RootState) => ItemDetailsSelectors.getFieldById(state))(fieldId);
const value = useSelector((state: RootState) => ItemDetailsSelectors.getEntryValue(state))(fieldId);
return (
<div>
{((): JSX.Element => {
const FieldType = fieldTypes[field.dataType];
if(FieldType) {
return <FieldType onChange={onChange} mode={mode} mandatory={mandatory} field={field} value={value} fieldId={fieldId}/>
} else {
return <div>{value}</div>;
}
})()}
</div>
)
}
现在,每个字段都具有相同的道具名称,但是名为value
的道具在每个组件中具有不同的类型。有些人期望一个数组,另外一个字符串,另外一个数字。...
我面临的问题是
const FieldType = fieldTypes[field.dataType];
if(FieldType) {
return <FieldType onChange={onChange} mode={mode} mandatory={mandatory} field={field} value={value} fieldId={fieldId}/>
} else {
return <div>{value}</div>;
}
返回以下错误以获取props值:
类型“ any”不能分配给类型“ never”。
如果我让所有孩子都期望它可以使用任何类型的值,但我想保留孩子类型。
有办法吗?
答案 0 :(得分:1)
我不确定如何在此处给出具体答案,因为您在示例代码中使用了一堆未知的帮助程序和类型。一般来说,我想到了两种选择来处理value
的键入:
1。)将基本类型注释为fieldTypes
,该基本类型将value
声明为any
:
type BaseProps<T> = {
value: T;
};
const TextField = (p: BaseProps<string>) => <span>{p.value}</span>;
const RadioField = (p: BaseProps<boolean>) => <span>{p.value}</span>;
const fieldTypes: { [K: string]: (props: BaseProps<any>) => JSX.Element } = {
a: TextField,
b: RadioField
};
因此,您无需更改子组件类型即可期望value
类型的any
,只需更改fieldTypes
映射类型。没关系,您通过value
检索的useSelector(..)
将适合any
。
2。)通过类型保护/控制流缩小精确的value
类型:
const FieldDispatcher = (props: FieldDispatcherProps) => {
const value = useSelector( .. ) // value comes from somewhere
// field.dataType comes from somewhere
// lets assume, fieldTypes looks like {"a" : TextField , "b" : CheckboxField}
const dataType: keyof typeof fieldTypes = ...
let fieldTypeJsx: JSX.Element;
switch (dataType) {
case "a": {
// dataType narrowed to "a" here, so fieldTypes[dataType]
// contains the specific Field Comp
const FieldType = fieldTypes[dataType];
// depends on value type, if you have to type cast here
fieldTypeJsx = <FieldType value={value as string} />;
break;
}
case "b": {
// analogue to case "a"
const FieldType = fieldTypes[dataType];
fieldTypeJsx = <FieldType value={value as boolean} />;
break;
}
default: {
return <div>{value}</div>;
}
}
答案 1 :(得分:0)
这里的问题是,您将children
的类型声明为Array<never>
,因此,在传递子代时,由于至少有一个子代不是never
类型,因此子级数组是any
和according to the docs类型的数组:
[...] no 类型是
never
的子类型或可分配给never
本身的子类型。甚至any
也无法分配给never
。
因此,将children
更改为Array<any>
类型(或更具体的类型)将解决此问题。
但是,您提到您想保留孩子的类型。类型never
的数组似乎是children
数组的奇怪类型,而另一个类型(如Array<any>
)似乎更合适。另外,如果您确实需要将孩子保留为Array<never>
,则也许该道具不应该是children
,而应该是另一个道具。