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

访问对象时泛型导致的类型收窄丢失问题

访问对象时泛型导致的类型收窄丢失问题

看起来你遇到了泛型使用时类型收窄丢失的问题,先把你给出的代码和场景整理清楚,咱们一步步来捋:

我有一个包含子对象的结构,子对象里按key存储了不同的函数:

const listOps = {    
    lists: {
        create: {
            schema: SchemaLists.listsCreate,
            db: DbUsersService.listsCreate,
        },
    },
} as const;

type ListModelKind = keyof typeof listOps;

export class ApiLists {
    static async handleOp<
        T extends ListModelKind,
        K extends keyof (typeof listOps)[T],
    >({ listModel, op, params }: {
        listModel: T;
        op: K;
        params: unknown;
    }) {
        // 核心问题:访问 listOps[listModel][op] 时,TS无法正确收窄类型
        const operation = listOps[listModel][op];
        // 想调用 operation.db 或 operation.schema 时,类型推导失效
    }
}

我猜你是在handleOp方法里,当通过泛型参数listModel和op访问listOps的属性时,TypeScript没办法自动收窄到具体的操作类型,导致你没法安全地访问schema或者db属性,甚至没办法让params的类型和对应schema的输入类型绑定,对吧?

给你两个实用的解决思路:

1. 直接通过类型断言明确类型(简单直接)

如果只是想快速解决类型收窄问题,可以在访问listOps属性时添加类型断言,让TS明确知道当前操作的具体类型:

export class ApiLists {
    static async handleOp<
        T extends ListModelKind,
        K extends keyof (typeof listOps)[T],
    >({ listModel, op, params }: {
        listModel: T;
        op: K;
        params: unknown;
    }) {
        // 用类型断言关联泛型参数,让TS推导正确类型
        const operation = listOps[listModel][op] as (typeof listOps)[T][K];
        // 现在可以安全访问schema和db,类型推导完全正常
        const validatedParams = operation.schema.parse(params);
        const result = await operation.db(validatedParams);
        return result;
    }
}

2. 优化泛型关联,让类型自动推导(更优雅)

如果想让params的类型也自动和对应操作的schema输入类型绑定,我们可以进一步优化泛型定义,让TS全程自动跟踪类型:

// 先提取所有操作的通用类型
type ListOperation = typeof listOps[keyof typeof listOps][keyof typeof listOps[keyof typeof listOps]];
// 定义一个工具类型,用来提取对应操作的schema输入参数类型
type OperationParams<Op extends ListOperation> = Parameters<Op['schema']['parse']>[0];

export class ApiLists {
    static async handleOp<
        T extends ListModelKind,
        K extends keyof (typeof listOps)[T],
        Op extends (typeof listOps)[T][K]
    >({ listModel, op, params }: {
        listModel: T;
        op: K;
        params: OperationParams<Op>;
    }) {
        const operation = listOps[listModel][op] as Op;
        const validated = operation.schema.parse(params);
        return await operation.db(validated);
    }
}

这样调整后,不仅operation的类型会被正确收窄,连params参数都会自动匹配对应操作的schema输入类型,调用的时候TS会自动做类型校验,完全避免了类型丢失的问题。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 12:44:28