我正在处理React钩子,该钩子基于模式返回输入的道具(标签,值,onChange处理程序)。特定字段的模式具有“变量”字段,其值为“字符串”或“数字”。我想要实现一种特定的输出字段类型是基于架构“一般”地键入的。例如,如果架构中的属性“ variant”为“ string”,则在道具中会显示“ onStringChange”。如果“ variant”为“ number”,则为“ onNumberChange”。有什么办法可以做到这一点?
为清楚起见,以下是使用示例
const Form = () => {
const fieldsProps = createFieldsPropsHook({ // <--- this is an example of using the function with "schema"
firstname: {
label: "Your firstname",
variant: 'string' // <--- variant 'string' so I want "onStringChange" handler
},
age: {
label: "Your age",
variant: 'number' // <--- variant "number" so I want "onNumberChange"
}
})
return (<div>
<Input
value={ fieldsProps.firstname.value }
label = { fieldsProps.firstname.label }
onChange = {fieldsProps.firstname.onStringChange} // <--- string handler
/>
<Input
value={ fieldsProps.age.value }
label={ fieldsProps.age.label }
onChange={fieldsProps.age.onNumberChange} // <--- number handler
/>
</div>)
}
对于上面的示例,我想这样输出
fieldsProps: {
firstname: {
onStringChange: (v: any) => void
// label, etc...
},
age: {
onNumberChange: (v: any) => void
// label, etc...
}
}
这是我的尝试
type Schema = Record<string, { variant: 'string', label: string } | { variant: 'number', label: string }>
type StringFieldProps = { onStringChange: (value: string) => void, label: string, value: string }
type NumberFieldProps = { onNumberChange: (value: number) => void, label: string, value: number }
function createFieldsPropsHook<T extends Schema>(schema: T) {
// ... some implementation ...
return output as Record<keyof T, StringFieldProps | NumberFieldProps>
}
但是我只知道所有字段都是相同的,并且没有处理程序
那么,如何根据模式更改单个输出字段的类型?可能吗 在打字稿中?
答案 0 :(得分:2)
您需要在每个键上进行映射(映射类型如{ [K in keyof T]: SomeType }
),以便处理每个键的变体。
然后,您需要一种方法来根据该值查找字段道具返回类型。为此,我们创建一个中间类型,将变体与其输出类型进行匹配:
type VariantLookup = {
string: StringFieldProps
number: NumberFieldProps
}
这应该使添加更多变体("date"
,"checkbox"
等)非常容易
现在我们可以像这样键入返回值:
function createFieldsPropsHook<T extends Schema>(schema: T): {
[K in keyof T]:
VariantLookup[T[K]["variant"]]
} {
// TODO: Implement...
return {} as any
}
T[K]["variant"]
从架构中获取"string"
或"number"
,而VariantLookup[...]
从查找助手类型中返回字段道具类型。
是否可以将“变量”设为可选?例如,如果未定义“变体”,则使用StringFieldProps
当然可以!
首先将您的架构类型更改为此:
type Schema = Record<string, { variant?: 'string' | 'number', label: string }>
这表示变量是字符串,数字或完全丢失。这样我们就可以检查'variant'属性,而不会出现类型错误。
现在,我们可以使用条件类型来检查variant
是否作为查找类型中的键存在。如果是这样,则使用该变体返回类型,否则返回默认值StringFieldProps
function createFieldsPropsHook<T extends Schema>(schema: T): {
[K in keyof T]:
T[K]["variant"] extends keyof Schema
? VariantLookup[T[K]["variant"]]
: StringFieldProps
} {
// TODO: Implement...
return {} as any
}