如何指定接口特定类型?TypeScript类型收窄问题求助
TypeScript类型收窄问题:区分EmptyElement与Annonce/Annonce2
问题场景与错误
我有一个Carousel组件,有数据时渲染带数据的卡片,无数据时渲染骨架屏。当前遇到TypeScript类型错误:
Type 'EmptyElement' is not assignable to type 'Annonce | Annonce2'.
Type 'EmptyElement' is missing the following properties from type 'Annonce2': ....
业务代码
if (biens.length) { return ( <Carousel data={data} renderElement={(bien) => { if (bien.id === 'isEmptyMock') return <SkeletonCardDernierBien isEmptyMock />; return ( <Component key={bien.id} annonce={bien} /> ); }} /> ); }
接口定义
import { Annonce } from '.../Annonce/Annonce'; import { Annonce2 } from '.../Annonce2'; export type EmptyElement = { id: string; }; export interface MyProps { biens: (Annonce | Annonce2 | EmptyElement)[]; }
需求:让TypeScript识别当if (bien.id === 'isEmptyMock')时,bien的类型为EmptyElement,其余情况为Annonce或Annonce2。
解决方案
1. 修改EmptyElement的id为字面量类型
TypeScript需要明确的类型区分特征,把EmptyElement的id从泛型string改为固定字面量,让类型系统能直接通过id值区分类型:
export type EmptyElement = { id: 'isEmptyMock'; // 固定为特定值,而非任意string };
2. 约束Annonce/Annonce2的id范围(可选)
如果能修改Annonce和Annonce2的接口,可以给它们的id添加约束,明确排除'isEmptyMock':
// 修改Annonce接口 interface Annonce { id: Exclude<string, 'isEmptyMock'>; // 原有其他属性... } // 修改Annonce2接口 interface Annonce2 { id: Exclude<string, 'isEmptyMock'>; // 原有其他属性... }
3. 自定义类型守卫函数
如果没法修改原有接口,写一个类型守卫函数来帮TypeScript做类型判断:
// 定义类型守卫 function isEmptyElement(bien: Annonce | Annonce2 | EmptyElement): bien is EmptyElement { return bien.id === 'isEmptyMock'; } // 在renderElement中使用 renderElement={(bien) => { if (isEmptyElement(bien)) return <SkeletonCardDernierBien isEmptyMock />; // 此时TypeScript会自动推断bien为Annonce | Annonce2 return ( <Component key={bien.id} annonce={bien} /> ); }}
4. 临时方案:类型断言(不推荐)
如果以上方法都无法实施,可临时用类型断言跳过检查,但这会失去TypeScript的类型保护,不建议长期使用:
return ( <Component key={bien.id} annonce={bien as Annonce | Annonce2} /> );
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

