I am writing a library where I generate sql statements with parameters. I am hoping I can add a bit of typescript magic to make it so that when an empty list of parameters is provided, I can make that function parameter optional. I am not sure how to accomplish this generically. Here is the basic type:
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()
obviously this function would expect {} when calling .all. My next thought was that an undefined arg could be skipped:
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()
I am hoping someone here has an idea on how I can make this work. Perhaps there is some typescript magic that I can do using tuples? In reality, building out this statement is much more elaborate, I have simplified here to show the problem.