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

TypeScript如何让函数根据参数返回动态类型(无需显式定义K)

解决TypeScript泛型函数自动推导列类型的问题

问题原因

你原本的写法给泛型K设置了默认值keyof T,当只显式传入T时,TypeScript会直接使用这个默认值,不会从columns参数推导K的实际类型,导致返回的类型总是全量字段的Pick<User, keyof User>[]。

解决方案:使用函数重载

通过重载函数区分传入具体列数组和*的两种场景,既实现自动推导列类型,又保留*的全量查询能力:

// 重载1:传入具体列数组,自动推导选中的字段类型
get<T, K extends keyof T>(
    tableName: string,
    columns: K[],
    where?: (query: Knex.QueryBuilder) => void,
    trx?: Knex.Transaction
): Promise<Pick<T, K>[]>;

// 重载2:传入'*',返回全量字段类型
get<T>(
    tableName: string,
    columns: '*',
    where?: (query: Knex.QueryBuilder) => void,
    trx?: Knex.Transaction
): Promise<T[]>;

// 函数实现
get<T, K extends keyof T>(
    tableName: string,
    columns: K[] | '*',
    where?: (query: Knex.QueryBuilder) => void,
    trx?: Knex.Transaction
): Promise<Pick<T, K>[] | T[]> {
    let query = this.withTransaction(tableName, trx).select(columns);

    if (where) {
        where(query);
    }

    return query;
}

使用效果

现在调用时无需显式传入K类型,TypeScript会自动推导:

const user = await this.db.get<User>(USER_TABLE_NAME, ['id', 'username', 'role']);
// user 的类型自动推导为 Pick<User, 'id' | 'username' | 'role'>[]

// 传入'*'时返回全量字段
const fullUser = await this.db.get<User>(USER_TABLE_NAME, '*');
// fullUser 的类型为 User[]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:46:20