Цепочка вызовов из опциональных аргументов
Описание
Пытаюсь создать что-то похожее на function.bind
, чтобы можно было использовать вот так:
const builder = new Builder<[number, string, boolean]>();
builder
.partial(42)
.partial("hello", true)
.build();
builder
.partial(42)
.partial()
.build("hello", true);
builder
.partial(42)
.partial("hello")
.build(true);
То есть Builder
-у нужны аргументы [number, string, boolean]
но их можно передать частично, главное, что в конце - во время build
все было передано.
Вот и, собственно, создал:
class Builder<T extends any[]> {
partial<A extends any[], B extends any[]>(this: Builder<[...A, ...B]>, ...arg: A): Builder<B> {
throw new Error("Method not implemented");
}
build(...args: T): void {
throw new Error("Method not implemented");
}
}
Теперь хочу делать так чтобы в partial
можно было передавать не массив аргументов, а конкретно 1 опциональный аргумент. То есть:
const builder = new Builder<[number, string, boolean]>();
builder
.partial(42) // Ok
.partial("hello", true) // Error. Partial has no pverload with 2 arguments
.build();
builder
.partial(42) // Ok
.partial() // Ok
.build("hello", true);
builder
.partial(42) // Ok
.partial("hello") // Ok
.build(true);
Опциональность очень конфликтует со spead-оператором (...), и он рассчитывает типы неправильно.
Вопрос
Подскажете как правильно это реализовать?
Дополнительно 1
Один из моих (наверно самый удачный) попыток:
class Builder<T extends any[]> {
partial<A extends [unknown], B extends any[]>(this: Builder<[...A, ...B]>, ...arg: A): Builder<B> {
throw new Error("Method not implemented");
}
build(...args: T): void {
throw new Error("Method not implemented");
}
}
const builder = new Builder<[number, string, boolean]>();
builder
.partial(42) // Норм
.partial("hello", true) // Ошибка, как и ожидалось
.build();
builder
.partial(42) // Норм
.partial() // Ошибка, которой не должно было быть
.build("hello", true);
Вот еще один:
class Builder<T extends any[]> {
partial<A extends any, B extends any[]>(this: Builder<[A, ...B]>, arg?: A): Builder<B> {
throw new Error("Method not implemented");
}
build(...args: T): void {
throw new Error("Method not implemented");
}
}
const builder = new Builder<[number, string, boolean]>();
builder
.partial(42) // Норм
.partial("hello", true) // Ошибка, как и ожидалось
.build();
builder
.partial(42) // Норм
.partial() // Норм
.build("hello", true); // Ошибка. string пропустил, ожидает только boolean