如何修复TypeScript联合类型Media的属性不存在错误?
问题
从API获取影视数据时,API返回电影和剧集两种不同结构:
- 剧集包含
name、original_name、origin_country、first_air_date字段 - 电影包含
original_title、release_date、title、video字段
二者还有一些共同属性,因此定义了TypeScript联合类型Media:
export type Media = { adult: boolean; backdrop_path?: string; genre_ids: number[]; id: number; original_language: string; overview: string; popularity: number; poster_path?: string; vote_average: number; vote_count: number; } & ( | { original_title: string; release_date: string; title: string; video: boolean; } | { first_air_date: string; name: string; origin_country: string[]; original_name: string; } );
但在以下场景使用时,出现类型错误:Property 'original_title' does not exist on type 'Media'和Property 'original_name' does not exist on type 'Media':
... <View> {moviesData.results.map((result: Media) => ( <Text key={result.id}>{result.original_title}</Text> ))} </View> <View> {showsData.results.map((result: Media) => ( <Text key={result.id}>{result.original_name}</Text> ))} </View> ...
解决方案
1. 拆分独立类型(推荐)
既然moviesData和showsData分别对应电影和剧集,先拆分出独立的Movie和TVShow类型,再通过联合类型得到Media:
// 定义共同属性 type MediaCommon = { adult: boolean; backdrop_path?: string; genre_ids: number[]; id: number; original_language: string; overview: string; popularity: number; poster_path?: string; vote_average: number; vote_count: number; }; // 电影类型 export type Movie = MediaCommon & { original_title: string; release_date: string; title: string; video: boolean; }; // 剧集类型 export type TVShow = MediaCommon & { first_air_date: string; name: string; origin_country: string[]; original_name: string; }; // 保留联合类型 export type Media = Movie | TVShow;
之后给数据指定对应类型,错误即可消除:
<View> {moviesData.results.map((result: Movie) => ( <Text key={result.id}>{result.original_title}</Text> ))} </View> <View> {showsData.results.map((result: TVShow) => ( <Text key={result.id}>{result.original_name}</Text> ))} </View>
2. 使用类型守卫
如果不想拆分类型,可以编写类型守卫函数判断当前Media的具体类型:
function isMovie(media: Media): media is Movie { return 'original_title' in media; } function isTVShow(media: Media): media is TVShow { return 'original_name' in media; }
使用时先做类型校验:
<View> {moviesData.results.map((result: Media) => ( <Text key={result.id}>{isMovie(result) ? result.original_title : ''}</Text> ))} </View> <View> {showsData.results.map((result: Media) => ( <Text key={result.id}>{isTVShow(result) ? result.original_name : ''}</Text> ))} </View>
3. 类型断言(不推荐,仅临时应急)
如果能确定当前数据一定是某类型,可以用类型断言强制跳过TypeScript的类型检查:
<View> {moviesData.results.map((result: Media) => ( <Text key={result.id}>{(result as Movie).original_title}</Text> ))} </View> <View> {showsData.results.map((result: Media) => ( <Text key={result.id}>{(result as TVShow).original_name}</Text> ))} </View>
这种方法会绕过类型校验,若数据结构不符可能引发运行时错误,仅建议临时使用。
内容的提问来源于stack exchange,提问作者Ahmet
相关产品推荐
相关产品推荐

