如何通过对象映射React组件收窄TypeScript联合类型,替代switch?
解决TypeScript组件映射的类型收窄问题
不用switch语句的话,可以通过给组件映射表定义精确的关联类型,让TypeScript自动识别object的具体类型,或者用泛型组件实现更优雅的类型推导。
方案一:给组件映射表绑定精确类型
通过定义一个类型映射,把type字段值和对应的对象类型关联起来,再让组件映射表遵循这个类型约束,TypeScript就能自动完成类型收窄:
import React from 'react' interface Foo { type: 'foo' } interface Bar { type: 'bar' } // 定义type值到对象类型的映射 type TypeToObjectMap = { foo: Foo; bar: Bar; }; type ObjectTypes = TypeToObjectMap[keyof TypeToObjectMap]; const FooForm = ({ object }: { object: Foo }) => { return <form>I'm a form for foos</form> } const BarForm = ({ object }: { object: Bar }) => { return <form>I'm a form for bars</form> } // 定义组件映射表,严格遵循TypeToObjectMap的类型约束 const componentMap: { [K in keyof TypeToObjectMap]: React.FC<{ object: TypeToObjectMap[K] }>; } = { foo: FooForm, bar: BarForm, }; const ObjectForm = ({ object }: { object: ObjectTypes }) => { const Form = componentMap[object.type as keyof TypeToObjectMap]; // 此时TypeScript能自动识别object的类型与Form的props匹配 return <Form object={object} /> }
方案二:泛型组件实现类型推导
把ObjectForm定义为泛型组件,让TypeScript根据传入的object类型自动推断对应的表单组件:
import React from 'react' interface Foo { type: 'foo' } interface Bar { type: 'bar' } type ObjectTypes = Foo | Bar; const FooForm = ({ object }: { object: Foo }) => { return <form>I'm a form for foos</form> } const BarForm = ({ object }: { object: Bar }) => { return <form>I'm a form for bars</form> } // 泛型版本的组件映射表,用as const锁定类型 const componentMap = { foo: FooForm, bar: BarForm, } as const; // 泛型组件,T约束为ObjectTypes的子集 const ObjectForm = <T extends ObjectTypes>({ object }: { object: T }) => { const Form = componentMap[object.type]; return <Form object={object} />; };
这两种方案都避免了switch语句的冗余代码,同时让TypeScript能正确收窄类型,不会出现类型错误。
内容的提问来源于stack exchange,提问作者user1032752
相关产品推荐
相关产品推荐

