Я в основном пытаюсь сделать что-то вроде этого:

interface gen1<T> {
    constructor(param: T);
}
interface gen2<T> {
    constructor(param: gen1<any>);
}
class genImpl implements gen2<any> {
    constructor(param: gen1<any>) {

    }
}

Но получаю ошибку:

Class 'genImpl' incorrectly implements interface 'gen2<any>'.
  Types of property 'constructor' are incompatible.
    Type 'Function' is not assignable to type '(param: gen1<any>) => any'.
      Type 'Function' provides no match for the signature '(param: gen1<any>): any'.
2
Brian 24 Апр 2017 в 03:52

2 ответа

Лучший ответ

Сигнатуры конструктора в интерфейсах не могут быть реализованы в классах. Это по замыслу. Из документации:

При работе с классами и интерфейсами полезно помнить, что класс имеет два типа: тип статической стороны и тип стороны экземпляра. Вы можете заметить, что если вы создаете интерфейс с сигнатурой конструкции и пытаетесь создать класс, реализующий этот интерфейс, вы получаете ошибку:

interface ClockConstructor {
    new (hour: number, minute: number);
}

class Clock implements ClockConstructor {
    currentTime: Date;
    constructor(h: number, m: number) { }
}

Это потому, что когда класс реализует интерфейс, проверяется только сторона экземпляра класса. Поскольку конструктор находится в статической стороне, он не включен в эту проверку.

Вместо этого вам нужно будет работать непосредственно со статической стороной класса. В этом примере мы определяем два интерфейса: ClockConstructor для конструктора и ClockInterface для методов экземпляра. Затем для удобства мы определяем функцию конструктора createClock, которая создает экземпляры типа, который передается ей.

interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("beep beep");
    }
}
class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("tick tock");
    }
}

let digital = createClock(DigitalClock, 12, 17); let analog =
createClock(AnalogClock, 7, 32); 

Поскольку первый параметр createClock имеет тип ClockConstructor, в createClock (AnalogClock, 7, 32) он проверяет, что AnalogClock имеет правильную сигнатуру конструктора.

Связанное обсуждение: https://github.com/Microsoft/TypeScript/issues/8917

7
Saravana 24 Апр 2017 в 01:28

Возможно ли иметь дженерики в конструкторе?

Да

но получаю ошибку

Причина в том, что gen<T> отличается от T

Fix

interface gen<T> {
    constructor(param: T);
}

class genImpl implements gen<any> {
    constructor(param: any) {

    }
}

То есть используйте any там, где когда-либо T использовали. (вы сделали ошибку, поместив T в gen<any> и any)

-1
basarat 24 Апр 2017 в 00:53