Как я могу вернуть класс из функции TypeScript?

Я использую TypeScript с библиотекой инъекций зависимостей, которая очень похожа на Angular 1 - в основном: зарегистрируйте factory с вашими зависимостями в качестве аргументов.

Вот как я зарегистрировал бы класс в ES6

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

Если я пишу то же самое в TypeScript:

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

Не удается скомпилировать с ошибкой

ошибка TS4025: экспортированная переменная 'factory' имеет или использует личное имя 'Foo'.

Можно ли разрешить TypeScript возвращать класс из функции factory?

Ответ 1

Быстрый ответ

измените это:

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

:

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

Более длинный ответ

Эта ошибка может быть вызвана/принудительной установкой tsconfig.json:

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

Но это не причина, это просто триггер. Настоящая причина (как обсуждалось здесь Ошибка при экспорте функции, возвращающей класс: Экспортированная переменная имеет или использует личное имя) происходит из компилятора Typescript

когда компилятор TS обнаруживает такой оператор

let factory = () => { ...

он должен начать угадывать, что такое тип возврата, потому что эта информация отсутствует (отметьте : <returnType>):

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

в нашем случае TS быстро узнает, что возвращенный type легко угадать:

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

поэтому, если бы у нас был такой же оператор (это не то же самое, что и исходный оператор вообще, но просто попробуйте использовать его в качестве примера, чтобы выяснить, что происходит), мы можем правильно объявить тип возврата:

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

этот подход будет работать, поскольку класс Foo экспортируется, т.е. отображается во внешний мир.

Вернемся к нашему делу. Мы хотим вернуть тип, который не экспортируется. И тогда мы ДОЛЖНЫ помочь компилятору TS решить, что такое тип возврата.

Он может быть явным любым:

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

Но даже лучше было бы иметь какой-то публичный интерфейс

export interface IFoo {}

И затем используйте такой интерфейс как тип возврата:

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

Ответ 2

Вам нужно также экспортировать класс, чтобы потребитель метода мог получить доступ к типу.

Обычно factory возвращает экземпляр, а не класс или конструктор.

Ответ 3

Вы ищете возвращаемый тип класса из функции? Ниже приведен фрагмент кода, как мы можем реализовать factory в TypeScript, как на других языках.

    class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}
class Factory{
    getObject(msg:string): Greeter {
        return new Greeter(msg);
    }
}
var greeter = new Factory().getObject("Hi");
console.log(greeter.greet());

Ответ 4

Я боролся с той же ошибкой. Решение для меня состояло в том, чтобы удалить

"declaration": true

из tsconfig.json или установить его на false.