У меня есть функция-конструктор, которая должна возвращать другой тип в зависимости от параметра.
interface B {
hello(): string;
}
class Foo {
constructor(withB: boolean): Foo & B;
constructor();
constructor(withB?: boolean) {
if (withB) {
Object.assign(this, { hello() {}})
}
}
}
const foo1 = new Foo();
const foo3 = new Foo(true);
Но это не работает. Как мне это сделать?






Вы не можете определить такой класс напрямую. Вы можете определить свой обычный класс и переименовать его в FooImpl, объявить константу, представляющую конструктор с перегрузками dirrent, и назначить ему FooImpl:
interface B {
hello(): string;
}
class FooImpl {
constructor(withB?: boolean) {
if (withB) {
Object.assign(this, { hello() {}})
}
}
}
const Foo : {
new(withB: boolean): FooImpl & B;
new() : FooImpl;
}= FooImpl as any;
const foo1 = new Foo(); // FooImpl
const foo3 = new Foo(true); // FooImpl & B
Если в вашем интерфейсе есть только методы, вы также можете обойтись без дженериков и указать параметр this в методах интерфейса, ограничив их видимость только определенными параметрами для типа:
interface B {
hello(): string;
}
class Foo<T=void> {
private withB: T;
constructor(withB: T) ;
constructor();
constructor(withB?: boolean) {
}
hello(this: Foo<boolean>): string {
return "";
}
}
const foo1 = new Foo();
foo1.hello() // Invalid
const foo3 = new Foo(true);
foo3.hello() // Valid
Спасибо за ответ. Что, если мне нужно расширить Foo? Это все еще будет работать?
Мне интересен ваш последний подход, но я его не понял. Насколько действителен метод hello, когда вы передаете true?
Что касается вашего первого пункта, я не знаю и не могу сейчас протестировать, я вернусь к вам по этому поводу, но я ожидаю, что вам нужно сделать то же самое для производных типов. Второй подход основан на том, что вы можете указать, какой тип должен иметь этот параметр. Если у вас есть this, который действителен только для определенного универсального параметра, метод не будет вызываться, если указаны другие общие параметры.
Есть ли какие-то обновления по этому поводу или этот ответ все еще хороший?
@Strebler, первый подход все еще работает, второй работает, но менее идеален, поскольку они перестали фильтровать элементы по параметру this. Нет новых языковых функций, которые упростили бы эту реализацию.
Задача конструктора - вернуть тип класса, для которого он является конструктором. Я бы рекомендовал использовать статический метод. Ваша проблема также может поддаться миксины в зависимости от того, что вы пытаетесь сделать.