Использование параметризованного класса TypeScript в качестве параметра типа - PullRequest
0 голосов
/ 15 декабря 2018

Недавний TypeScript (3.1) имеет потрясающие функции с выводами типов.Было бы очень полезно иметь возможность сделать это со строгой проверкой типов:

class Foo {
  constructor(a: number, b: string) {}
}

function create<T extends new(...args: any[]) => any>(
    cls: T, ...args: ConstructorParameters<T>): InstanceType<T> {
  return new cls(...args);
}

let a: Foo = create(Foo, 18, "a");   // <-- yay, fully typechecked

Но я не могу найти способ сделать это, когда мой класс универсален (параметризован):

class Bar<T> {
  constructor(a: T, b: string) {}
}

let b = create(Bar, "asdf", "a");          // <--- not typechecked
let c = create(Bar<number>, 20, "a");              // <--- error
let d = create<typeof Bar<number>>(Bar, 20, "a");  // <--- error

Как мне это сделать?

1 Ответ

0 голосов
/ 15 декабря 2018

Проблема в том, что общий параметр T в Bar<T>, кажется, применяется только к части экземпляра Bar, а не к статической части, хотя T используется в сигнатуре конструктора (а конструктор принадлежитстатическая часть).

Обходной путь должен иметь явный интерфейс, который определяет статическую часть, , как предлагается в этом ответе , и использовать функцию "высшего порядка" Bar<T>() вместо класса:

function create<T extends new(...args: any[]) => any>(
    cls: T, ...args: ConstructorParameters<T>): InstanceType<T> {
  return new cls(...args);
}


interface BarConstructor<T, C> {
  new(a: T, b: string): C;
}

class BarImpl<T> {
  constructor(a: T, b: string) {}
}

function Bar<T>(): BarConstructor<T, BarImpl<T>> {
  return BarImpl;
}


let b = create(Bar(), "asdf", "a"); // OK because Bar() by itself implies Bar<{}>(),
                                   // and "asdf" is assignable to {}
  // you can turn it into an error by having `never` as default for T like this
  // function Bar<T = never>()

let c = create(Bar<number>(), "asdf", "a"); // error as expected
let d = create(Bar<number>(), 20, "a");    // OK
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...