函数的现有重载相匹配?"/>
如何确保我的 TypeScript 重载与 knex 库的 select 函数的现有重载相匹配?
我想从
select
库中向现有的 knex
函数添加另一个签名,以便执行类型检查。在我的 JavaScript 实现中,我使用 prototype
覆盖它来满足我的特定要求。
这个新签名指示 TypeScript 在传递给
select
函数的接口中不存在键时以及传递的对象中缺少键时抛出错误。
这是新签名的代码:
export interface Select<TRecord extends {} = any, TResult = unknown[]> {
<TRecord extends {}>(
obj: { [K in keyof TRecord]: TRecord[K] extends object ? QueryBuilder<TRecord[K], TRecord[K]> : string }
): QueryBuilder<TRecord[], TRecord[]>;
}
但是,可能还有其他现有的过载可能导致我的过载被忽略。
我想知道我是否可以做些什么来确保我的重载符合 TypeScript 的期望。
import { Knex as OriginalKnex, knex } from "knex";
export interface User {
id: number;
name: string;
age?: number;
accounts: Account[];
}
export interface Account {
foo: number;
}
declare module "knex" {
export namespace Knex {
export interface Select<TRecord extends {} = any, TResult = unknown[]> {
<TRecord extends {}>(obj: { [K in keyof TRecord]: TRecord[K] extends object ? QueryBuilder<TRecord[K], TRecord[K]> : string }): QueryBuilder<TRecord[], TRecord[]>;
}
////// select2 is a new function for proof the typing is working:
export interface Select2<TRecord extends {} = any, TResult = unknown[]> {
<TRecord extends {}>(obj: { [K in keyof TRecord]: TRecord[K] extends object ? QueryBuilder<TRecord[K], TRecord[K]> : string }): QueryBuilder<TRecord[], TRecord[]>;
}
interface QueryInterface<TRecord extends {} = any, TResult = any> {
select2: Select2<TRecord, TResult>;
}
}
}
const db = knex({});
const accounts = db("account").select<Account>({ foo: "foo" });
const user = await db("user")
.select<User>({ id: "id", name: "id", age: "age", bla: "blue" }) //<--- should throw "bla" is not exist in User interface.
.first(); // <-- should return User | undefined
// ^?
const user2 = await db("user")
.select2<User>({ id: "id", name: "id", age: "age", bla: "blue" }) //<--- should throw "bla" is not exist in User interface.
.first(); // <-- should return User | undefined
// ^?
游乐场
回答如下:更多推荐
如何确保我的 TypeScript 重载与 knex 库的 select 函数的现有重载相匹配?
发布评论