Ссылка на универсальный конструктор и статический метод в TypeScript

#typescript #generics

#typescript #общие сведения

Вопрос:

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

 class Wrapper<T> {

    public static forConstructor<S extends Object>(construc: { new (...args: any[]): S }): Wrapper<S> {
        return new Wrapper<S>();
    }
}

class A {
    private aaa: string = null;
}

class B {
    private bbb: string = null;
}

const wrapper: Wrapper<A> = Wrapper.forConstructor(B);// LINE X
  

Однако в СТРОКЕ X Wrapper<A> = Wrapper<B> это неверно, TypeScript не показывает ошибку в этой строке. В чем моя ошибка?

Комментарии:

1. В настоящее Wrapper<A> время и Wrapper<B> являются структурно совместимыми. Если вы сохраните переданный конструктор как поле (например), вы получите сообщение об ошибке

2. @AlekseyL. Я изменил поля, добавил разные методы, конструкторы — не помогло.

3. Я говорю об обертке. Я добавлю пример

Ответ №1:

В настоящее Wrapper<A> время и Wrapper<B> являются структурно совместимыми. Если вы сохраните переданный конструктор как поле (например), вы получите сообщение об ошибке:

 type Constructor<T> = new (...args: any[]) => T;

class Wrapper<T> {
    constructor(private c: Constructor<T>){}

    public static forConstructor<T>(construc: Constructor<T>): Wrapper<T> {
        return new Wrapper<T>(construc);
    }
}

class A {
    private aaa: string = null;
}

class B {
    private bbb: string = null;
}

const wrapper: Wrapper<A> = Wrapper.forConstructor(B); // error
  

<a rel="noreferrer noopener nofollow" href="https://www.typescriptlang.org/play/index.html#src=type Constructor = new (…args: any[]) => T;

class Wrapper {
constructor(private c: Constructor){}

public static forConstructor(construc: Constructor): Wrapper {
return new Wrapper(construc);
}
}

class A {
private aaa: string = null;
}

class B {
private bbb: string = null;
}

const wrapper: Wrapper = Wrapper.forConstructor(B); // error» rel=»nofollow noreferrer»>Игровая площадка

Ответ №2:

Статический метод не может использовать аргумент типа экземпляра Wrapper<T> , поскольку static не ограничен экземпляром. Ваша сигнатура метода <S extends Object по сути означает any объект. Таким образом, безопасность типов вообще отсутствует. Вот почему tscompiler не жалуется на

 const wrapper: Wrapper<A> = Wrapper.forConstructor(B);// LINE X
  

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

 class Wrapper<S> {

    public forConstructor(construc: { new (...args: any[]): S }): Wrapper<S> {
        return new Wrapper<S>();
    }
}

const wrapper: Wrapper<A> = new Wrapper();
wrapper.forConstructor(B); // will not work
  

Комментарии:

1. A static method can not use the instance type argument Wrapper<T> since static is not instance bounded. конечно, я это знаю. Вот почему общий параметр для класса есть T , а для статического метода есть S . И мне нужен только статический метод. Возможно ли это сделать?

2. Вы не можете использовать Wrapper<T> as T в своем статическом методе. Итак, нет, это невозможно.