如何检查泛型 K 是不是属于泛型 M |打字稿通用 |还原

Posted

技术标签:

【中文标题】如何检查泛型 K 是不是属于泛型 M |打字稿通用 |还原【英文标题】:How to check if generic K is part of generic M | Typescript Generic | Redux如何检查泛型 K 是否属于泛型 M |打字稿通用 |还原 【发布时间】:2021-02-19 22:08:46 【问题描述】:

我正在尝试减少我的反应应用程序中的 Bolilderplate。我正在使用 Redux 状态并已决定使用哪个 Redux 结构(请参阅上下文)。现在我想让它变小。为此,我创建了一个通用的 actionCreator。我的问题是找到所需的通用语法。

通用动作创建器

这是我对动作生成器的通用方法。

export class genericAction<M, K> extends Action 
    public reducer = (state: M) => ( ...state, ...this.payload );

    constructor(public readonly type: string | undefined, public payload: K) 
        super();
    

目前只能合并状态,但我的目标是一个可选参数,它是一个函数。然后,此功能将允许我执行自定义状态合并(例如 state.count + 有效负载)。但这是一个不同的话题。

问题

我的问题是我可以使用 fubar: number 而不是 loading: boolean 。显然 fubar 不是我的 ProductStateModel 的一部分。

const someAction = new genericAction<ProductStateModel,  loading: boolean >(ProductListActionTypes.REQUEST_START,  loading: true );

问题

我只想使用 ProductStateModel 的属性作为通用 K 的类型。 伪代码:

genericAction<M, K is type of M> extends Action

总体思路是使用以下类型和参数创建动作:

状态模型 ProductListActionType 有效载荷

这可能吗?还是有通用/替代解决方案?如果需要,我可以对 StateModel 进行更改。我是 redux 的新手,想把它做好。我试图在通用方法中获取 Pick ,但现在我不确定这是否可能是我需要的方式,或者我应该只是去睡觉:D

感谢您的任何提示和帮助


上下文

这是我的出发点

// State
export interface State 

export interface ProductStateModel extends State 
    products: Array<ProductDTO>;
    loading: boolean;
    error: string;



// Product Actions
export abstract class Action 
    public readonly type: string | undefined;
    protected constructor() 
        return Object.assign(, this);
    
    abstract reducer(state: State): State;


// First of 3 Actions. They are all very similar. The generic function should replace all of them.
export class ProductListRequest extends Action 
    public readonly type = ProductListActionTypes.REQUEST_START;
    public reducer = (state: ProductStateModel) => ( ...state, loading: this.payload.loading );

    constructor(public payload: Pick<ProductStateModel, 'loading'>) 
        super();
    


// Reducer
export const productListReducer = (state: ProductStateModel = defaultProductState, action: Action) => 
    return isNil(action.reducer) ? action.reducer(state) : state;
;

【问题讨论】:

【参考方案1】:
export class genericAction<M> extends Action 
    public reducer = (state: M) => ( ...state, ...this.payload );

    constructor(public readonly type: string | undefined, public payload: Partial<M>) 
        super();
    

我删除了第二种类型并将 Partial 添加到有效负载泛型类型中。在我的脑海中,我想像在 Pick&lt;ProductStateModel, 'loading'&gt; 的原始方法中那样限制允许的属性,但后来我意识到这不是必需的。泛型类的新调用是我定义此操作需要哪些属性的唯一地方,这很好。

【讨论】:

以上是关于如何检查泛型 K 是不是属于泛型 M |打字稿通用 |还原的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:如何创建 Array 泛型类型,其中包含具有给定接口的每个 keyof 实例的对象

打字稿泛型,获取数组内容的类型

打字稿泛型类参数

打字稿:强制默认通用类型为“any”而不是“”

打字稿:允许泛型类型仅是具有“字符串”属性的对象

获取泛型函数的类型而不调用打字稿中的函数