【问题标题】:How to create a factory that returns anonymous classes that implement a generic interface如何创建返回实现通用接口的匿名类的工厂
【发布时间】:2017-03-24 22:15:37
【问题描述】:

我们正在使用带有 Angular/TypeScript 的 ngrx。为了给 Actions 添加一些类型安全性,我们创建了以下内容

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;
        }
    }
}

为了摆脱锅炉位置代码,我想我可以创建一个生成这些类的函数。

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

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

TS2322 类型“typeof TypedActionImpl”不可分配给类型“TypedAction”。缺少属性“类型”。

我所做的工作

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

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 中返回泛型类的动态实现是不可能的吗?

【问题讨论】:

  • 你试过返回typeof:export function createTypedActionConstructor&lt;T&gt;(type: string): typeof TypedAction&lt;T&gt; {}
  • 我做到了......这甚至在语法上都无效

标签: generics typescript type-safety ngrx


【解决方案1】:

应该是:

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

编辑

另一种选择是添加多个函数签名:

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 };
...

【讨论】:

  • 这很好,唯一的问题是我一直在做以下事情:export type ExtensionActions = ExtensionRegistrationAction | ExtensionRegistrationFailedAction | ExtensionRegistrationSucceededAction; 这种方法不允许。它也不允许我将某些东西转换为那种类型:您知道解决方法吗?
  • 检查我修改后的答案
猜你喜欢
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多