Функция смешивания Typescript с необязательным суперклассом - PullRequest
1 голос
/ 12 марта 2019

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

interface Test {
  readonly __TEST: "test";
  new (...args: any[]): {
    readonly test: "test";
  };
}

function TestMixin<SuperClass extends new (...args: any[]) => any>(
  superClass?: SuperClass
) {
  const defaultClass = class {};
  /* Error: Type 'new (...args: any[]) => any' is not assignable to type 'SuperClass extends undefined ? typeof defaultClass : undefined'.ts(2322) */
  const sc: typeof superClass extends undefined ? typeof defaultClass : undefined = superClass === undefined ? defaultClass : superClass;

  /* Error: Type 'SuperClass extends undefined ? typeof defaultClass : undefined' is not a constructor function type. */
  class T extends sc implements InstanceType<Test> {
    public static readonly __TEST = "test";
    public readonly test = "test";
  }

  return T;
}

Ответы [ 2 ]

1 голос
/ 12 марта 2019

Вы не можете расширять условный тип, Typescripts ожидает, что предложение в предложении extends будет конструктором, а не любым другим более сложным типом.

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

interface Test {
    readonly __TEST: "test";
    new(...args: any[]): {
        readonly test: "test";
    };
}

function TestMixin<SuperClass extends new (...args: any[]) => any = new () => {}>(
    superClass?: SuperClass
) {
    const defaultClass = class { };
    /* ok */
    const sc = (superClass === undefined ? defaultClass : superClass) as SuperClass;

    /* Ok now */
    class T extends sc implements InstanceType<Test> {
        public static readonly __TEST = "test";
        public readonly test = "test";
    }

    return T;
}

let a = TestMixin();
new a().test;

let b = TestMixin(class {
    constructor(n: number) { console.log("Hi") }
    m() { }
});
new b(1).test;
new b(1).m();

Пока никто не указывает явный параметр типа для TestMixin и пропускает параметр, он должен работать нормально.

0 голосов
/ 12 марта 2019

Найдите общий знаменатель - тип Constructor.

interface Constructor<T = any> {
  new (...args: any[]): T;
}
interface Test {
    readonly __TEST: "test";
    new(...args: any[]): {
        readonly test: "test";
    };
}

interface Constructor<T = any> {
  new (...args: any[]): T;
}

function TestMixin<SuperClass extends new (...args: any[]) => any>(
    superClass?: SuperClass
) {
    const defaultClass: Constructor = superClass || class { };

    return class T extends defaultClass implements InstanceType<Test> {
        public static readonly __TEST = "test";
        public readonly test = "test";
    }
}
...