Búsqueda de sitios web

javascript - ¿Cómo puedo devolver una clase desde una función de TypeScript?


Estoy usando TypeScript con una biblioteca de inyección de dependencias que funciona de manera muy similar a Angular 1 - básicamente: registrar una fábrica con tus dependencias como argumentos.

Así es como registraría una clase en ES6

export let factory = () => {
    return class Foo {}
};

Si escribo lo mismo en TypeScript:

export let factory = () => {
    return class Foo {}
};

Falla al compilar con el error

error TS4025: La variable exportada 'factory' tiene o está usando un nombre privado 'Foo'.

¿Hay alguna manera de permitir que TypeScript devuelva una clase desde una función fábrica?

Respuesta #1

Respuesta rápida

cambia esto:

export let factory = () => {
    return class Foo {}
};

a eso:

export let factory = () : any => {
    return class Foo {}
};

Respuesta más larga

Este error podría ser activado/forzado por una configuración de tsconfig.json:

{
    "compilerOptions": {
        ...
        "declaration": true // this should be false or omitted

Pero esa no es la razón, es solo un desencadenante. La verdadera razón (como se discute aquí Error al exportar función que devuelve clase: La variable exportada tiene o está usando un nombre privado) proviene del compilador de Typescript

cuando el compilador de TS encuentra una instrucción como esta

let factory = () => { ...

debe empezar a adivinar cuál es el tipo de retorno, porque falta esa información (ver el marcador de posición : <returnType>):

let factory = () : <returnType> => { ...

en nuestro caso, TS descubrirá rápidamente que el type devuelto es fácil de adivinar:

return class Foo {} // this is returned value, 
                    // that could be treated as a return type of the factory method

entonces, en caso de que tuviéramos esa declaración similar (esto no es lo mismo que la declaración original en absoluto, pero vamos a intentar usarla solo como un ejemplo para aclarar lo que sucede) podemos declarar correctamente el tipo de retorno:

export class Foo {} // Foo is exported
export let factory = () : Foo => { // it could be return type of export function
    return Foo
};

ese enfoque estaría funcionando, porque la clase Foo está exportada, es decir, visible para el mundo exterior.

Volviendo a nuestro caso. Queremos devolver un tipo que no es exportado. Y luego, DEBEMOS ayudar al compilador de TS a decidir cuál es el tipo de retorno.

Podría ser explícito cualquiera:

export let factory = () : any => {
    return class Foo {}
};

Pero aún mejor sería tener alguna interfaz pública

export interface IFoo {}

Y luego usa tal interfaz como tipo de retorno:

export let factory = () : IFoo => {
    return class Foo implements IFoo {}
};

Respuesta #2

Respuesta tardía a una pregunta antigua:

Necesitas tener la clase definida fuera del método de fábrica y definir el valor de retorno usando 'typeof'.

class Foo {}

export const factory = (): typeof Foo => {
    return Foo;
};

Artículos relacionados