如何让TypeScript识别渲染器与section的类型关联以解决类型报错?
问题场景
我需要实现一个接收sections列表并渲染的函数,简化后的示例代码如下:
enum SectionType { Image = 'image', Title = 'title', } type ImageSection = { type: SectionType.Image; image: string; }; type TitleSection = { type: SectionType.Title; title: string; }; type Section = ImageSection | TitleSection; type SectionOfType<T> = Extract<Section, { type: T }>; const SECTION_RENDERERS: {[T in SectionType]: (section: SectionOfType<T>) => string } = { [SectionType.Image]: (section) => section.image, [SectionType.Title]: (section) => section.title, } function renderUpsellSection(section: Section) { return SECTION_RENDERERS[section.type](section); }
在renderUpsellSection()函数中,遇到了TS编译报错:
TS2345: Argument of type Section is not assignable to parameter of type never
The intersection ImageSection & TitleSection was reduced to never because property type has conflicting types in some constituents.
Type ImageSection is not assignable to type never
需要让TypeScript识别SECTION_RENDERERS[section.type]与section之间的类型关联。
解决方案
方法1:使用类型断言缩小范围
直接对传入的section进行类型断言,明确它对应当前renderer的参数类型:
function renderUpsellSection(section: Section) { return SECTION_RENDERERS[section.type](section as SectionOfType<typeof section.type>); }
这种方式简单直接,利用SectionOfType工具类型匹配对应的section类型,让TypeScript认可参数的兼容性。
方法2:封装泛型辅助函数
通过泛型函数建立section.type和参数类型的强关联,避免类型歧义:
function renderSection<T extends SectionType>(type: T, section: SectionOfType<T>) { return SECTION_RENDERERS[type](section); } function renderUpsellSection(section: Section) { return renderSection(section.type, section); }
泛型函数renderSection会根据传入的type自动推导对应的SectionOfType<T>类型,TypeScript能清晰识别两者的关联关系。
方法3:用类型守卫拆分分支
通过条件判断触发TypeScript的类型窄化,让每个分支里的section类型被明确识别:
function renderUpsellSection(section: Section) { if (section.type === SectionType.Image) { return SECTION_RENDERERS[section.type](section); } else { return SECTION_RENDERERS[section.type](section); } }
这种方式无需额外语法,仅通过分支判断就让TypeScript自动处理类型关联,不会出现never报错。
内容的提问来源于stack exchange,提问作者Misho Tektumanidze

