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());
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.)
O operador 'typeof' não pretende descrever o construtor de um tipo, mas sim o tipo de um valor. SomeGeneric
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.
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.
Uma solução para isso é definir um tipo genérico para descrever construtores como o Angular faz:
de ( angular / packages / core / src / type.ts )
Exemplo de uso: