You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TypeScript中Promise响应类型异常,类型校验失效排查

解决OMDb API类型校验异常问题

问题现象

  • 正常电影数据(IOMDb类型)能通过isObjOfType<IOMDbError>(data)校验,错误存入omdbErrorMsg状态
  • 无效输入返回的错误响应(IOMDbError类型)能通过isObjOfType<IOMDb>(data)校验,调用sanitizeOMDbResponse时因movie.Genre不存在抛出Cannot read properties of undefined错误

核心原因

自定义类型断言函数isObjOfType<T>仅判断对象非空,未实现真实的类型结构校验,导致响应数据错误匹配类型分支。

解决方案

1. 实现精准的类型守卫函数

针对IOMDb和IOMDbError的结构特征,编写专属类型校验函数:

// 校验IOMDb类型(可根据需求添加更多必填字段校验)
export function isIOMDb(obj: unknown): obj is IOMDb {
  return (
    typeof obj === 'object' &&
    obj !== null &&
    'Title' in obj &&
    typeof (obj as IOMDb).Title === 'string'
  );
}

// 校验IOMDbError类型
export function isIOMDbError(obj: unknown): obj is IOMDbError {
  return (
    typeof obj === 'object' &&
    obj !== null &&
    'Response' in obj &&
    'Error' in obj &&
    typeof (obj as IOMDbError).Response === 'string' &&
    typeof (obj as IOMDbError).Error === 'string'
  );
}

2. 调整响应处理逻辑

替换原有的类型断言,用新的守卫函数做精准判断,同时避免状态更新导致的无限循环:

useEffect(() => {
  if (searchTerm.length !== 0) {
    // 预处理搜索词,避免直接修改状态触发重复渲染
    const processedSearchTerm = searchTerm.replace(/ /g, '+');
    
    getOMDbMovie(processedSearchTerm).then((data) => {
      // 先重置状态,清除旧数据干扰
      setOmdbErrorMsg(null);
      setOmdbMovie(null);

      if (isIOMDbError(data)) {
        setOmdbErrorMsg(data);
      } else if (isIOMDb(data) && Array.isArray(genres)) {
        const omdb = sanitizeOMDbResponse(data, genres);
        omdb && setOmdbMovie(omdb);
      }
    });
  }
}, [searchTerm]);

3. 优化数据处理函数的容错性

即使通过类型校验,仍需处理字段缺失的情况:

function sanitizeOMDbResponse(
  movie: IOMDb,
  genresFromDB: IGenre[]
): IMovieOMdb | null {
  // 处理Genre字段可能不存在的情况,添加默认值
  const genreLowerCase = movie.Genre?.toLowerCase().split(', ') || [];

  // 简化筛选逻辑,直接过滤匹配的分类
  const newGenres = genresFromDB.filter(genre => genreLowerCase.includes(genre.name));

  // 确保核心字段存在再返回结果
  if (movie.Title && movie.Plot && movie.Poster) {
    return {
      title: movie.Title,
      description: movie.Plot,
      coverImage: movie.Poster,
      genres: newGenres,
    };
  }

  return null;
}

4. 简化组件中的状态判断

由于状态已通过TypeScript泛型限定类型,直接判断非空即可:

{omdbMovie && <OMDbMovieDetails omdbMovie={omdbMovie} />}
{omdbErrorMsg && !omdbErrorMsg.Response && (
  <MessageComponent message={omdbErrorMsg.Error} />
)}

内容的提问来源于stack exchange,提问作者qouillyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:45:36