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

TypeScript中API响应JSON数据的泛型类型映射异常问题

解决API响应序列化与反序列化的类型不匹配问题

你的问题核心出在Stringified<T>泛型的类型判断逻辑上,主要有两个问题:

  • Date在TypeScript中属于object子类型,会被原逻辑误判为对象进行递归处理,导致Date类型被解析成Stringified<Date>而非string;
  • 数组类型的处理逻辑错误,原代码直接对数组类型递归Stringified<T[key]>,而不是对数组元素进行类型转换。

修正后的Stringified<T>泛型

重新调整类型判断的优先级,先处理Date和数组类型,再处理普通对象:

type Stringified<T> = 
  // 优先处理Date类型,直接映射为string
  T extends Date ? string :
  // 处理数组:提取元素类型U,对每个元素应用Stringified后组成数组
  T extends Array<infer U> ? Stringified<U>[] :
  // 处理普通对象:递归映射每个属性
  T extends object ? { [K in keyof T]: Stringified<T[K]> } :
  // 数字、布尔类型保持原类型
  T extends number | boolean ? T :
  // 其他类型统一转为string
  string;

修正后的API响应类型

替换原有的ApiResponse定义即可:

type ApiResponse<T> = {
    success: true;
    data: Stringified<T>
} | {
    success: false;
    errors: string[]
}

验证hydrateEvent函数

此时Stringified<Event>会正确解析响应类型:

  • start/end字段被识别为string;
  • visibility字段被解析为嵌套的Stringified<{ host: boolean; bands: boolean; public: boolean }>,和Event['visibility']结构完全匹配。

修正后的hydrateEvent函数不再有类型错误:

type Event = {
    id: string;
    name: string;
    start: Date;
    end: Date;
    visibility?: {
        host: boolean,
        bands: boolean,
        public: boolean
    }
}

function hydrateEvent(rawEvent: Stringified<Event>){
    const event: Event = {
        id: rawEvent.id,
        name: rawEvent.name,
        start: new Date(rawEvent.start),
        end: new Date(rawEvent.end)
    };

    if(rawEvent.visibility){
        event.visibility = rawEvent.visibility;
    }

    return event;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:15:37