Typescript -条件可选的通用函数参数

qq24tv8q  于 2022-11-18  发布在  TypeScript
关注(0)|答案(1)|浏览(203)

我正在写一个库,在其中生成带参数的sql语句。我希望我可以添加一些typescript魔术,以便当提供空的参数列表时,我可以使该函数参数可选。我不知道如何一般性地实现这一点。下面是基本类型:

class Statement<Params> {
    exec(params: Params) { /* do stuff */ }
    all(params: Params) { /* do stuff */ }
    one(params: Params) { /* do stuff */ }
}

const create_stmt = new Statement<{ username: string; password: string }>()
create_stmt.exec({ username: 'bob', password: 'secret' })

const list_stmt = new Statement<{}>()
// What I want is to skip this argument since I know its just an empty object. As expected though, there is a type error: "An argument for 'params' was not provided."
const rows = list_stmt.all()

很明显,这个函数在调用.all时需要{}。我的下一个想法是可以跳过undefined参数:

type OptionalOnEmpty<T> = keyof T extends never ? T | undefined : T

class Statement<Params> {
    exec(params: OptionalOnEmpty<Params>) { /* do stuff */ }
    all(params: OptionalOnEmpty<Params>) { /* do stuff */ }
    one(params: OptionalOnEmpty<Params>) { /* do stuff */ }
}

const create_stmt = new Statement<{ username: string; password: string }>()
create_stmt.exec({ username: 'bob', password: 'secret' })

const list_stmt = new Statement<{}>()
// this still fails, I have to at the very least, pass list_stmt.all(undefined)
const rows = list_stmt.all()

我希望这里有人能告诉我如何才能使这个工作。也许有一些打字脚本魔术,我可以做使用元组?在现实中,建立这个语句是更复杂的,我简化了这里显示的问题。

ctehm74n

ctehm74n1#

您忽略了将extends Package 成元组以使其不是分配的:

type Perhaps<T> = [keyof T] extends [never] ? [] : [T];

另外,请注意,我现在返回的是元组而不是TT | undefined。这是因为,现在我们将使用Perhaps作为函数接受的所有参数的类型(作为rest参数),而不是直接为参数指定类型:

class Statement<Params> {
    exec(...[params]: Perhaps<Params>) { /* do stuff */ }
    all(...[params]: Perhaps<Params>) { /* do stuff */ }
    one(...[params]: Perhaps<Params>) { /* do stuff */ }
}

Perhaps给我们一个空元组时,该方法不接受任何参数;当它给我们[T]时,params的类型是T
现在,当Params{}时,可以这样做:

const rows = list_stmt.all(); // okay

Playground

相关问题