Gostaria de criar uma classe chamável que Foo(...args)
seja idêntica e new Foo(...args)
ao mesmo tempo mantenha a verificação de tipo do TypeScript satisfatória.
Em tempo de execução, isso é fácil, basta encapsular a classe com um Proxy implementando apply.
O problema é que qualquer função que retorna um Proxy não pode especificar o tipo de classe e a interface da classe passada.
No TypeScript, a class Foo ...
expressão cria um valor like const Foo = ...
e uma interface like interface Foo ...
ao mesmo tempo.
Mas não consigo adicionar a interface ao tipo de retorno da função wrapper.
const Foo = wrap(class Foo {
x
y
constructor(x: number, y: number) {
this.x = x
this.y = y
}
})
function wrap<T>(ctor: T): T {
return ctor
}
const foo: Foo = new Foo(1, 2)
Esta última linha dá o erro:
'Foo' se refere a um valor, mas está sendo usado como um tipo aqui. Você quis dizer 'typeof Foo'?ts(2749)
Mas adicionar typeof é claramente a solução errada, pois significaria o próprio Foo.
Posso resolver isso retirando a classe do wrapper:
class _Foo {
x
y
constructor(x: number, y: number) {
this.x = x
this.y = y
}
}
const Foo = wrap(_Foo)
interface Foo extends _Foo { }
function wrap<T>(ctor: T): T {
return ctor
}
const foo: Foo = new Foo(1, 2)
Mas isso tem três problemas:
- Requer que eu use o nome
_Foo
que é simplesmente feio - Requer que a classe esteja no contexto do valor de retorno de wrap()
- Requer muitas repetições da palavra
Foo
(cinco vezes!)
Sugestões sobre como resolver isso?
Eu recomendaria não usar essa abordagem porque:
Proxy
isso pode reduzir o desempenho em cerca de 6 vezes.Uma função de fábrica seria suficiente e suportaria herança e, portanto, manutenção/extensão:
Parque infantil