TypeScript如何实现支持动态泛型参数的可复用FormState类型
可以实现,先解释下你原来的写法为什么不生效:TypeScript 目前原生不支持直接把泛型接口本身作为类型参数传入(也就是不支持高阶泛型参数直接调用的写法),所以你直接写R<string>是无法被识别的。
这里提供两种落地的实现方案,你可以根据自己的使用场景选:
方案1:极简通用替换方案(适合所有表单字段都是同一类型的场景)
你的原代码里所有表单的字段类型都是同一个泛型T,这种场景下用字段类型替换的映射类型实现最方便:
// 工具类型:把传入对象的所有字段类型替换为指定的新类型 type ReplaceAllFieldType<SourceObj, NewType> = { [Key in keyof SourceObj]: NewType } // 定义可复用的 FormState 泛型 type FormState<R extends object> = { form: ReplaceAllFieldType<R, string> validate: ReplaceAllFieldType<R, boolean> } // 使用示例 // 1. 用你原有Form的场景 type DefaultFormState = FormState<Form<unknown>> // 2. 自定义表单的场景 interface CustomForm<T> { username: T age: T address: T } type CustomFormState = FormState<CustomForm<unknown>>
这种方案的好处是写法简单,不需要额外的类型定义,只要传入任意表单结构的实例类型即可,泛型参数填unknown/any都可以,后续会被工具类型统一替换成目标类型。
方案2:高阶泛型兼容方案(适合表单字段类型不统一的复杂场景)
如果你的自定义表单的字段不一定是同一个泛型类型,需要完整保留泛型接口的逻辑,可以用载体类型绕一层实现高阶泛型的效果:
// 定义泛型载体接口,用来传递泛型构造信息 interface GenericCarrier<T = unknown> { readonly _marker?: T } // 工具类型:从载体中提取指定泛型参数的最终类型 type ApplyGeneric<Carrier extends GenericCarrier, Param> = ReturnType<Carrier<Param>> // 定义可复用的 FormState 泛型 type FormState<R extends GenericCarrier> = { form: ApplyGeneric<R, string> validate: ApplyGeneric<R, boolean> } // 使用示例 // 1. 先给原有Form定义对应的载体 interface FormCarrier extends GenericCarrier { <T>(): Form<T> } type DefaultFormState = FormState<FormCarrier> // 2. 自定义表单的场景 interface CustomForm<T> { username: T age: `${T}` isAdult: boolean } interface CustomFormCarrier extends GenericCarrier { <T>(): CustomForm<T> } type CustomFormState = FormState<CustomFormCarrier>
这种方案可以完整保留你原泛型接口的所有类型逻辑,适合复杂的表单结构场景。
内容的提问来源于stack exchange,提问作者reznikovkg
相关产品推荐
相关产品推荐

