简体   繁体   English

如何在 TypeScript 中创建动态 class?

[英]How to create a dynamic class in TypeScript?

I'm trying to migrate a project from JavaScript to TypeScript.我正在尝试将项目从 JavaScript 迁移到 TypeScript。 I'm attempting to use the following code.我正在尝试使用以下代码。

// CustomError.ts
class ErrorType {
    defaultMessage: string;
    errorName: string;

    constructor(defaultMessage: string, errorName: string) {
        this.defaultMessage = defaultMessage;
        this.errorName = errorName;
    }

    errorConstructor() {
        const {defaultMessage, errorName} = this;

        class CustomError extends Error {
            name: string;
            message: string;

            constructor(message: string) {
                super();
                this.name = errorName;
                this.message = message || defaultMessage;
                return this;
            }
        }
        return CustomError;
    }
}

export = {
    "InvalidThing": new ErrorType("Invalid Thing", "InvalidThing").errorConstructor()
};


// ---------------------------------------------------------------------------------------------------


// main.ts
// import CustomError from "./CustomError";
// const main = () => throw new CustomError.InvalidThing("Thing A is invalid.");
// main();

// other.js
// const CustomError = require("./CustomError");
// const main = () => throw new CustomError.InvalidThing("Thing A is invalid.");
// main();

The problem is I'm getting the following error.问题是我收到以下错误。

Default export of the module has or is using private name 'CustomError'.(4082)模块的默认导出具有或正在使用私有名称“CustomError”。(4082)

Somehow I need to get CustomError to be in a higher scope.不知何故,我需要让CustomError处于更高的 scope 中。 But the problem with that is that I need to be able to access that errorName & defaultMessage .但问题是我需要能够访问那个errorNamedefaultMessage

I'm also aware that I could just create a CustomError class for every error type.我也知道我可以为每种错误类型创建一个CustomError class 。 But in my actual code, I have roughly 8 error types.但在我的实际代码中,我大约有 8 种错误类型。 Which would mean a LOT of repeated code.这意味着很多重复的代码。 I'd prefer to keep it DRY and not repeat a bunch of code.我宁愿让它保持干燥,而不是重复一堆代码。

How can I do this in TypeScript without errors?我怎样才能在 TypeScript 中做到这一点而不会出错?


You can also view a TypeScript Playground with this code to see the error it's throwing.您还可以使用此代码查看 TypeScript Playground 以查看它引发的错误。

The ErrorType class looks mostly superfluous to me - all it's being used for is to be able to create a CustomError instance with certain properties. ErrorType class 对我来说几乎是多余的——它的全部用途是能够创建具有某些属性的CustomError实例。 To fix your problem, and to make the code much more concise, consider using a higher-order function instead, to which you can pass the defaultMessage and errorName , and returns a function that takes a message and returns a CustomError instance with the desired properties:为了解决您的问题并使代码更简洁,请考虑使用更高阶的 function 代替,您可以将defaultMessageerrorName传递给它,并返回一个 function 接收消息并返回具有所需属性的CustomError实例:

class CustomError extends Error {
    name: string;
    message: string;

    constructor(message: string, defaultMessage: string, errorName: string) {
        super();
        this.name = errorName;
        this.message = message || defaultMessage;
        return this;
    }
}
const makeError = (
    defaultMessage: string,
    errorName: string,
) => (message: string) => new CustomError(message, defaultMessage, errorName);
export = {
    "InvalidThing": makeError("Invalid Thing", "InvalidThing")
};

Because the InvalidThing property is now a plain function, call it without new :因为InvalidThing属性现在是一个普通的 function,所以在没有new的情况下调用它:

throw CustomError.InvalidThing("Thing A is invalid.");

If the consumer must keep calling it with new , it's uglier since Typescript requires new targets to be classes or functions, which cannot return anything explicitly.如果消费者必须继续用new调用它,那就更难看了,因为 Typescript 要求new的目标是类或函数,它们不能显式返回任何东西。 For the currying sort of thing you're looking for to work, you'll have to have every value of the exported object be a new class:对于您正在寻找工作的柯里化类型的东西,您必须将导出的 object 的每个值都设为新的 class:

const makeError = (
    defaultMessage: string,
    errorName: string,
) => class CustomError extends Error {
    public name: string;
    public message: string;

    constructor(message: string) {
        super();
        this.name = errorName;
        this.message = message || defaultMessage;
    }
};
const exportedObj = {
    InvalidThing: makeError('Invalid Thing', 'InvalidThing'),
};

throw new exportedObj.InvalidThing('Thing A is invalid.');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM