Перегрузка конструктора TypeScript возвращает разные типы

У меня есть функция-конструктор, которая должна возвращать другой тип в зависимости от параметра.

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);

Но это не работает. Как мне это сделать?

Задача конструктора - вернуть тип класса, для которого он является конструктором. Я бы рекомендовал использовать статический метод. Ваша проблема также может поддаться миксины в зависимости от того, что вы пытаетесь сделать.

morsecodist 10.06.2018 06:27
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
1
1
813
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете определить такой класс напрямую. Вы можете определить свой обычный класс и переименовать его в 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? Это все еще будет работать?

undefined 10.06.2018 13:25

Мне интересен ваш последний подход, но я его не понял. Насколько действителен метод hello, когда вы передаете true?

undefined 10.06.2018 13:33

Что касается вашего первого пункта, я не знаю и не могу сейчас протестировать, я вернусь к вам по этому поводу, но я ожидаю, что вам нужно сделать то же самое для производных типов. Второй подход основан на том, что вы можете указать, какой тип должен иметь этот параметр. Если у вас есть this, который действителен только для определенного универсального параметра, метод не будет вызываться, если указаны другие общие параметры.

Titian Cernicova-Dragomir 10.06.2018 15:47

Есть ли какие-то обновления по этому поводу или этот ответ все еще хороший?

ostrebler 10.02.2020 22:48

@Strebler, первый подход все еще работает, второй работает, но менее идеален, поскольку они перестали фильтровать элементы по параметру this. Нет новых языковых функций, которые упростили бы эту реализацию.

Titian Cernicova-Dragomir 11.02.2020 06:23

Другие вопросы по теме