Typescript: Use typeof com genérico

Criado em 15 dez. 2017  ·  3Comentários  ·  Fonte: microsoft/TypeScript

Versão do TypeScript: versão atual do playground (?)

Código

class GenericGroup<T> {
  items: Array<T> = [];
  constructor(name: string) {}
}

type CheckboxValues = string;
type CheckboxesGroup = new (name: string) => GenericGroup<CheckboxValues>;
const Checkboxes: CheckboxesGroup = GenericGroup;
const checkboxes = new Checkboxes('checkboxes');
checkboxes.items.map(item => item.toUpperCase());


type RadioValues = string;
type RadiosGroup = typeof GenericGroup<RadioValues>;
const Radios: RadiosGroup = GenericGroup;
const radios = new Radios('radios');
radios.items.map(item => item.toUpperCase());

ligação

Comportamento esperado:

typeof GenericGroup<RadioValues>; é equivalente a new (name: string) => GenericGroup<RadioValues>;

Comportamento real:

Erro de sintaxe, porque typeof GenericGroup<RadioValues>; não é compatível.

Motivação:

No meu caso de uso, tenho uma classe com um genérico (como GenericGroup ) que _estende_ uma classe de uma biblioteca de terceiros. A classe da biblioteca de terceiros usa vários parâmetros em seu construtor. Quando eu alias a minha classe com o genérico preenchido, não quero escrever os parâmetros para a biblioteca de terceiros todas as vezes (como feito com new (name: string) => GenericGroup<CheckboxValues>; ), pois eu realmente não os mantenho.

(Parece haver vários problemas relacionados, mas não consegui encontrar exatamente esse problema.)

Question

Comentários muito úteis

O operador 'typeof' não pretende descrever o construtor de um tipo, mas sim o tipo de um valor. SomeGenericnão é um valor, é um tipo em si mesmo. Qualquer outra interface / tipo (como o definido abaixo) também não funcionará dessa maneira.

interface MyInterface {
    name: string;
}

let m: typeof MyInterface; // error "MyInterface only refers to a type, but is being used as a value here."

Uma solução para isso é definir um tipo genérico para descrever construtores como o Angular faz:

// angular/packages/core/src/type.ts

export interface Type<T> extends Function { 
    new (...args: any[]): T; 
}

de ( angular / packages / core / src / type.ts )

Exemplo de uso:

type RadioValues = string;
type RadiosGroup = Type<GenericGroup<RadioValues>>;
const Radios: RadiosGroup = GenericGroup;
const radios = new Radios('radios');
radios.items.map(item => item.toUpperCase());

Todos 3 comentários

O operador 'typeof' não pretende descrever o construtor de um tipo, mas sim o tipo de um valor. SomeGenericnão é um valor, é um tipo em si mesmo. Qualquer outra interface / tipo (como o definido abaixo) também não funcionará dessa maneira.

interface MyInterface {
    name: string;
}

let m: typeof MyInterface; // error "MyInterface only refers to a type, but is being used as a value here."

Uma solução para isso é definir um tipo genérico para descrever construtores como o Angular faz:

// angular/packages/core/src/type.ts

export interface Type<T> extends Function { 
    new (...args: any[]): T; 
}

de ( angular / packages / core / src / type.ts )

Exemplo de uso:

type RadioValues = string;
type RadiosGroup = Type<GenericGroup<RadioValues>>;
const Radios: RadiosGroup = GenericGroup;
const radios = new Radios('radios');
radios.items.map(item => item.toUpperCase());

Uma coisa sutil é que as funções de construtor de classe genérica não estão contidas em um tipo genérico . Você pode dizer isso porque o parâmetro de tipo não está no escopo para membros estáticos! "Parece" que você tem um tipo como este

interface GenericCtor<T> {
  new(x: string): InstanceType<T>;
}

mas o tipo real é assim

interface GenericCtor {
  new<T>(x: string): InstanceType<T>;
}

Obrigado a ambos. Eu preciso envolver minha cabeça em torno disso. No meu caso, estendo a partir de um construtor de terceiros ( React.Component ), então preciso descobrir como aplicar seu feedback lá. Obrigado.

Esta página foi útil?
0 / 5 - 0 avaliações