Zod 配合 JSDoc 实现类型注释

javascript - How to infer Zod type in JSDoc (without TypeScript) - Stack Overflow
JavaScript 中使用了 Zod 实现了 Schema 之后,想要在 TypeScript 中的那种类型提示效果,也是可以支持的,依然是使用 Zodinfer 方法,只不过是需要在注释中使用.

使用方式

  1. 定义 Schema
export const TournamentItemSchema = z.object({
  tournament_id: z.number(),
  tournament_name: z.string(),
  tournament_logo_url: z.string().optional(),
  tournament_icon_url: z.string().optional(),
  tournament_banner_url: z.string().optional(),
  tournament_background_url: z.string().optional(),
  tournament_description: z.string().optional(),
  tournament_starttime: z.number(),
  tournament_endtime: z.number(),
  tournament_live: z.array(z.object({})).default([]),
});
 
/**
 * 列表
 */
export const TournamentListSchema = z.array(TournamentItemSchema);
  1. 将 Schema 转换为 JSDoc 类型
    这里需要使用到 JSDocimporttypeof 写法
/**
 * @typedef {import('zod').z.infer<typeof import('tournament.schema').TournamentListSchema>} List
 */
  1. 使用 JSDoc 类型
/**
 * @typedef {Object} TournamentContextType
 * @property {List} list - 锦标赛列表
 *
 * @returns {TournamentContextType}
 */
export const useTournamentContext = () => {
  const context = useContext(TournamentContext);
 
  if (context == null) {
    throw new Error('Tournament components must be wrapped in TournamentContext.Provider');
  }
 
  return context;
};
// list 的类型将会与 Schema 定义一一对应
const { list } = useTournamentContext();

结果:
CleanShot 2024-03-21 at 15.54.14@2x.png

另外一种组件的使用方式

'use client';
 
import Image from 'next/image';
 
/**
 * @typedef {import('zod').z.infer<typeof import('@/services/api/tournament.schema').TournamentItemSchema>} TournamentItemType
 */
 
/**
 * @param {Object} props
 * @param {TournamentItemType} props.item - 锦标赛信息
 */
const TournamentCarouselItem = ({ item, onClick }) => {
  const handlerClick = () => onClick(item);
 
  return (
    <div className='h-[100px] w-[238px] bg-gray-500' onClick={handlerClick}>
      <Image src={item.tournament_banner_url} alt={item.tournament_name} width={238} height={100} />
    </div>
  );
};
 
export default TournamentCarouselItem;