TypeScript映射返回类型报错:交集缩减为never的解决方案咨询
解决区分联合类型映射返回类型的交集冲突错误
问题根源
你的代码报错是因为TypeScript无法自动推断Array.find()返回的Integration(IntegrationA | IntegrationB)与泛型T对应的IntegrationData[T]之间的精确匹配关系。当泛型T是Integrations的联合类型时,IntegrationData[T]会被解析为IntegrationA & IntegrationB——但这两个类型的name属性类型冲突,最终被简化为never,导致类型赋值失败。
修复方案
1. 简化冗余类型
首先,IntegrationMap类型是多余的,直接通过IntegrationData[keyof IntegrationData]即可得到联合类型:
type Integration = IntegrationData[keyof IntegrationData];
2. 用类型谓词收窄类型(推荐)
通过自定义类型谓词,让TypeScript明确知道find找到的元素就是对应泛型T的类型:
enum Integrations { A = 'A', B = 'B', } type IntegrationA = { name: Integrations.A, propertyA: string; } type IntegrationB = { name: Integrations.B, propertyB: number; } type IntegrationData = { [Integrations.A]: IntegrationA; [Integrations.B]: IntegrationB; }; // 直接生成联合类型,无需多余的IntegrationMap type Integration = IntegrationData[keyof IntegrationData]; // 模拟数据源 const integrations: Integration[] = [ { name: Integrations.A, propertyA: "testA" }, { name: Integrations.B, propertyB: 123 } ]; // 自定义类型谓词,用于类型收窄 const isIntegrationOfType = <T extends Integrations>(i: Integration, name: T): i is IntegrationData[T] => { return i.name === name; }; const getIntegration = <T extends Integrations>(name: T): IntegrationData[T] => { const integration = integrations.find(i => isIntegrationOfType(i, name)); // 处理找不到的情况,避免返回undefined if (!integration) { throw new Error(`Integration ${name} not found`); } return integration; }; // 类型安全:typeof intB 为 IntegrationB const intB = getIntegration(Integrations.B);
3. 直接类型断言(适合确定必有匹配的场景)
如果能确保数据源中一定存在对应name的元素,也可以直接对find结果做类型断言:
const getIntegration = <T extends Integrations>(name: T): IntegrationData[T] => { const integration = integrations.find((i: Integration) => i.name === name) as IntegrationData[T]; if (!integration) { throw new Error(`Integration ${name} not found`); } return integration; };
原理说明
通过类型谓词或断言,我们明确告知TypeScript:找到的元素与输入的name参数类型严格对应,避免了泛型T作为联合类型时导致的IntegrationData[T]解析为冲突交集(never)的问题,同时保证了函数返回类型的动态性与类型安全。
内容的提问来源于stack exchange,提问作者Tyler Rhinehart
相关产品推荐
相关产品推荐

