Конструктор возврата универсального типа в TypeScript

Я изо всех сил пытаюсь определить, как написать код TypeScipt, в котором говорится, что этот конструктор возврата функции универсального типа. Существует множество примеров того, как передать конструктор универсального типа, но не как вернуть.

Пожалуйста, проверьте следующий пример:

Это часть абстрактного класса:

 getModel():  (new () => T) {
    throw new Error('Method not implemented.'); // Error because don't know how to fix it
}

В производном классе я пытаюсь реализовать это так:

getModel(): typeof User {
    return User;
}

У меня следующая ошибка:

Type '() => typeof User' is not assignable to type '() => new () => User'.

Я мог бы пропустить реализацию в производном классе, если бы знал, как указать в абстрактном классе.

Итак, вопрос в том, как указать на уровне абстрактного класса, что метод возвращает конструктор универсального типа, и я могу пропустить реализацию этого метода на уровне дочернего класса? Или, может быть, я неправильно указываю обратную подпись на уровне абстрактного класса?

Обновлено:

Пожалуйста, проверьте странную проблему. Классы A и B отличаются только наличием явного конструктора. И в RealA не работает, а в RealB работает тот же метод getModel ().

class A {
a = '';
constructor(a: string) {

}
}

class B {
    a = '';
    static test(): void {
        console.info('I do work');
    }
}

abstract class Base<T> {
    Prop: T;
    constructor(TCreator: { new (): T; }) {
        this.Prop = new TCreator();
    }

    getModel(): (new () => T) {
        throw new Error('Method not implemented.'); // Error because don't know how to fix it
    }
}

class RealA extends Base<A> {
    getModel(): typeof A { // doesn't work - compilation error
        return A;
    }
}

class RealB extends Base<B> {
    getModel(): typeof B { // works
        return B;
    }
}

var test = new RealA(A); // compile error
var test2 = new RealB(B)

Для класса RealA такая же ошибка

() => typeof A' is not assignable to type '() => new () => A'

Не могли бы вы опубликовать полный пример. Кажется, работает с тем, что вы предоставили: typescriptlang.org/play/…

Titian Cernicova-Dragomir 02.12.2018 16:32

Похоже, что ваш T по какой-то причине является типом конструктора, а не экземпляром. Обратите внимание, что тип User и значение User различаются и что тип typeof User не совпадает с типом User. Вы должны опубликовать минимальный воспроизводимый пример, чтобы кто-то точно определил проблему.

jcalz 02.12.2018 17:17

@ TitianCernicova-Dragomir, пожалуйста, проверьте исходный вопрос. Я его обновил.

Selvatico 02.12.2018 18:37

Не уверен, что это за вариант использования, но в качестве примечания - вы можете просто иметь getModel() { return this.constructor; } в базе вместо того, чтобы реализовывать его в каждом производном классе

Aleksey L. 03.12.2018 07:26
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
4 077
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Ошибка ожидается, поскольку конструктор класса A имеет обязательный аргумент. Абстрактный класс ограничивает передаваемый конструктор отсутствием аргументов (new () => T).

Простое решение - удалить конструктор A.

Если вы хотите иметь возможность передавать классы, у которых есть конструкторы, требующие аргументов, вам нужно будет изменить определение базового класса, чтобы захватить тип конструктора, и заставить constructor принимать эти обязательные аргументы (используя кортежи в остальные параметры)

class A {
    a = '';
    constructor(a: string) {

    }
}

class B {
    a = '';
    static test(): void {
        console.info('I do work');
    }
}

type ArgumentTypes<T> = T extends new (...a: infer A) => any? A : [] 
abstract class Base<T extends new (...a: any[])=> any> {
    Prop: InstanceType<T>;
    constructor(TCreator: T, ...a: ArgumentTypes<T>) {
        this.Prop = new TCreator(...a);
    }

    getModel(): T {
        throw new Error('Method not implemented.'); // Error because don't know how to fix it
    }
}

class RealA extends Base<typeof A> {
    getModel(): typeof A { // doesn't work - compilation error
        return A;
    }
}

class RealB extends Base<typeof B> {
    getModel(): typeof B { // works
        return B;
    }
}

var test = new RealA(A, ""); // ok
var test2 = new RealB(B)

Теперь это имеет большой смысл. Как было бы проще, если бы они поместили эту ошибку или подобное объяснение? Большое тебе спасибо. Буду думать над решением. Оба они, вероятно, неприменимы, потому что мы не можем использовать любой.

Selvatico 02.12.2018 19:05

@Selvatico в этом случае any - это просто заполнитель, он полностью безопасен по типу, any не попадет в общедоступную подпись класса или реализации. Он просто указывает компилятору, что конструктор может возвращать любой класс и может иметь любое количество аргументов любого типа. Когда вы передаете класс, он определяет аргументы и тип экземпляра, и на самом деле ничего не существует. Дайте мне знать, если я смогу еще помочь :)

Titian Cernicova-Dragomir 02.12.2018 20:08

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