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

组合类型在代码中丢失,如何确保data对象的类型安全?

类型组合问题:APIEndpoint与LoginToken组合后data仍为any类型

我有如下函数调用:

myapp.auth(formData).then((/**@type {(import('$lib/types').APIEndpoint & {data?: import('$lib/types').LoginToken}) | null}*/ response) => {
    if (!response) {
        console.log('error', 'no response from server');
        return;
    }
    if (response.status === 200) {
        // do stuff
        console.log(response.data);
    }
});

导入的类型定义如下:

export type APIEndpoint = {
    status: number;
    error: boolean;
    data?: any;
};
export type LoginToken = {
    username: string;
    id: number;
    isadmin: boolean;
    permissions: string[];
    fullname: string;
};

我希望对data对象强制执行类型安全,但悬停查看时它仍显示为data: any,请问我的类型组合方式是否正确?

VS Code中显示的response类型:(APIEndpoint & { data?: LoginToken | undefined; }) | null
VS Code中显示的response.data类型:any


问题原因

你当前的类型组合方式无效,因为APIEndpoint里的data?: any会覆盖交叉类型中data?: LoginToken的定义。TypeScript处理交叉类型时,若两个类型存在同名属性,宽泛的any类型不会被更具体的类型覆盖,反而会“污染”整个属性的类型。

正确解决方法

方法1:泛型重构APIEndpoint类型

这是最推荐的方案,让APIEndpoint支持泛型来指定data的类型:

export type APIEndpoint<T = any> = {
    status: number;
    error: boolean;
    data?: T;
};
export type LoginToken = {
    username: string;
    id: number;
    isadmin: boolean;
    permissions: string[];
    fullname: string;
};

之后在类型断言时直接使用泛型:

myapp.auth(formData).then((/**@type {import('$lib/types').APIEndpoint<import('$lib/types').LoginToken> | null}*/ response) => {
    if (!response) {
        console.log('error', 'no response from server');
        return;
    }
    if (response.status === 200) {
        console.log(response.data); // 此时data类型为LoginToken | undefined
    }
});

方法2:用Omit移除原有data属性后交叉

如果不想修改APIEndpoint的原始定义,可以使用Omit工具类型移除原有的data属性,再与包含LoginToken的data属性交叉:

myapp.auth(formData).then((/**@type {(Omit<import('$lib/types').APIEndpoint, 'data'> & {data?: import('$lib/types').LoginToken}) | null}*/ response) => {
    if (!response) {
        console.log('error', 'no response from server');
        return;
    }
    if (response.status === 200) {
        console.log(response.data); // 此时data类型为LoginToken | undefined
    }
});

两种方法都能让response.data获得正确的类型提示,实现类型安全。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 01:44:54