如何创建一个返回实现通用接口的匿名类的工厂 [英] How to create a factory that returns anonymous classes that implement a generic interface

查看:175
本文介绍了如何创建一个返回实现通用接口的匿名类的工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在Angular/TypeScript中使用了ngrx.为了在Actions中增加类型安全性,我们创建了以下内容

We are using ngrx with Angular/TypeScript. To add some type safety to Actions, we created the following

export interface TypedAction<T> extends Action {
    type: string;
    payload: T;
}

export class ExtensionRegistrationAction implements TypedAction<ExtensionRegistrationPayload> {
    readonly type = ExtensionActionTypes.REGISTER_EXTENSION;
    constructor(public payload: ExtensionRegistrationPayload) {}
}

export class ExtensionRegistrationSucceededAction implements TypedAction<void> {
    readonly type = ExtensionActionTypes.REGISTER_EXTENSION_SUCCESS;
    constructor(public payload: void) {}
}

export class ExtensionRegistrationFailedAction implements TypedAction<{messageCode: string}> {
    readonly type = ExtensionActionTypes.REGISTER_EXTENSION_FAILURE;
    constructor(public payload: {messageCode: string}) {}
}


export type ExtensionActions = ExtensionRegistrationAction
    | ExtensionRegistrationFailedAction
    | ExtensionRegistrationSucceededAction;

// The above lets us do the following
export function appExtensionsReducer(state: AppExtensionState = initialAppExtensionsState,
                                     action: ExtensionActions): AppExtensionState {
    switch (action.type) {
        case ExtensionActionTypes.REGISTER_EXTENSION: 
            const registerAction = action as ExtensionRegistrationAction;
            return {
                registrations: state.registrations.concat(registerAction.payload)
            };
        // Handle other actions...
        default: {
            return state;
        }
    }
}

要摆脱锅炉位代码,我想我可以创建一个生成那些类的函数.

To get rid of the boiler place code, I thought I could create a function that generates those classes.

export function createTypedActionConstructor<T>(type: string): TypedAction<T> {
    return class TypedActionImpl implements TypedAction<T> {
        readonly type = type;
        constructor(public payload: T) {}
    }
}

但是我得到一个错误,因为我返回的是实现TypedAction的类,而不是实例.错误提示:

But I get an error because what I'm returning is the class that implements TypedAction, not the instance. The error says:

TS2322类型'typeof TypedActionImpl'不能分配给类型'TypedAction'.属性类型"丢失.

TS2322 Type 'typeof TypedActionImpl' is not assignable to type 'TypedAction'. Property 'type' is missing.

我所做的工作

以下代码通过要求两个声明来解决该问题,一个声明用于实现T的接口,另一个声明用于创建该类型T的工厂函数.问题在于,它对样板代码膨胀没有太大帮助.

The following code gets around the problem by requiring two declarations, one for the interface that implements T and one for a factory function that creates that type T. The problem is that it doesn't help that much with boiler plate code bloat.

export function createTypedActionFactory<T>(type: string): (payload: T) => TypedAction<T> {
    return function(payload: T): TypedAction<T> {
        return {type, payload};
    }
}
// Now to create an action I need the two statements
export interface ExtensionRegistrationAction extends TypedAction<ExtensionRegistrationPayload> {}
export const createExtensionRegistrationAction = createTypedActionFactory<ExtensionRegistrationPayload>(
    ExtensionActionTypes.REGISTER_EXTENSION);

问题 从TypeScript返回动态类的动态实现是不可能的吗?

Question Is it impossible to return a dynamic implementation of a generic class from TypeScript?

推荐答案

应为:

export function createTypedActionConstructor<T>(type: string): { new (payload: T): TypedAction<T> } {
    ...
}


编辑

另一种选择是添加多个功能签名:


Edit

Another option is to add multiple function signatures:

export function createTypedActionConstructor(type: ExtensionActionTypes.REGISTER_EXTENSION_FAILURE): { new (payload: {messageCode: string}): ExtensionRegistrationFailedAction };
export function createTypedActionConstructor(type: ExtensionActionTypes.REGISTER_EXTENSION_SUCCESS): { new (payload: void): ExtensionRegistrationSucceededAction };
...

这篇关于如何创建一个返回实现通用接口的匿名类的工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆