TypeScript:如何强制转换通用对象? [英] TypeScript: How to cast a generic object?

查看:1225
本文介绍了TypeScript:如何强制转换通用对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下接口:

interface AppState {
  readonly grid : IGridSettings;
  readonly selected : ISelectedSettings;
}

interface IGridSettings {
  readonly extents : number;
  readonly isXY : boolean;
  readonly isXZ : boolean;
  readonly isYZ : boolean;
  readonly spacing : number;
}

interface ISelectedSettings {
  readonly bodyColor : number;
  readonly colorGlow : number;
  readonly lineColor : number;
  readonly selection : number[] | undefined;
}

interface Action<T = any> {
  type: T
}

interface SetPropertyValueAction<KAction extends keyof AppState, KActionProp extends keyof AppState[KAction]> extends Action {
  type : string;
  payload : {
    property : [KAction, KActionProp];
    value : IUserActions[KAction][KActionProp];
  };
}

最终,在发出setPropertyValue函数时,我的redux reducer会被调用:

Eventually my redux reducer gets called when the setPropertyValue function is emitted:

const setPropertyValue = <KAction extends keyof AppState, KActionProp extends keyof AppState[KAction]>( property : [KAction, KActionProp], value : AppState[KAction][KActionProp] ) : SetPropertyValueAction<KAction, KActionProp> => ( {
  type: 'SET_PROPERTY_VALUE',
  payload: {
    property,
    value,
  }
} );

function myReducer( state : AppState = INITIAL_STATE, a : Action ) : AppState {
  switch( a.type ) {
    case 'SET_PROPERTY_VALUE': {
      const action = a as SetPropertyValueAction; //  <- error here
      return createNewState( state, action.payload.property, action.payload.value );
    }
  }
  return states;
}

我遇到的问题是我不知道如何解决从Action到SetPropertyValueAction的转换。 TypeScript告诉我错误是:

The problem that I'm having is I don't know how to fix the cast from Action to SetPropertyValueAction. TypeScript tells me the error is:

Generic type 'SetPropertyValueAction<KAction, KActionProp>' requires 2 type argument(s).

我尝试将有错误的代码行更改为以下内容:

I tried changing the line of code that has the error to the following:

const action = a as SetPropertyValueAction<KAction extends keyof AppState, KActionProp extends keyof AppState[KAction]>;

...但这给了我两个错误,说找不到名称KAction和KActionProp

...but this gives me two errors saying 'Cannot find name KAction and KActionProp'

如何将Action对象转换为通用SetPropertyValueAction?

How can I cast an Action object to the generic SetPropertyValueAction ??

这是我其他问题的后续问题此处已回答的问题:如何添加TypeScript类型安全性到我的redux动作?

This is a follow up question to my other question that has been answered here: How to add TypeScript type safety to my redux action?

推荐答案

我们需要为该类型指定类型参数。由于我们并不真正了解它们,因此我们需要与T $$$的 key兼容的东西,但不是 T 未知不会执行,因为它不满足约束,我们可以使用的一种类型是 any 从不(它是任何类型的子类型)

We need to specify the type parameters for the type. Since we don't really know them, we need something that is compatible with keyof T but represent is not an actual key of T. unknown will not do since it does not satisfy the constraint, the one type we can use is any or never (which is a subtype of any type)

interface AppState {
    readonly grid: IGridSettings;
    readonly selected: ISelectedSettings;
}

interface IGridSettings {
    readonly extents: number;
    readonly isXY: boolean;
    readonly isXZ: boolean;
    readonly isYZ: boolean;
    readonly spacing: number;
}

interface ISelectedSettings {
    readonly bodyColor: number;
    readonly colorGlow: number;
    readonly lineColor: number;
    readonly selection: number[] | undefined;
}

interface Action<T = any> {
    type: T
}

interface SetPropertyValueAction<KAction extends keyof AppState, KActionProp extends keyof AppState[KAction]> extends Action {
    type: string;
    payload: {
        property: [KAction, KActionProp];
        value: AppState[KAction][KActionProp];
    };
}

const setPropertyValue = <KAction extends keyof AppState, KActionProp extends keyof AppState[KAction]>(property: [KAction, KActionProp], value: AppState[KAction][KActionProp]): SetPropertyValueAction<KAction, KActionProp> => ({
    type: 'SET_PROPERTY_VALUE',
    payload: {
        property,
        value,
    }
});
declare const INITIAL_STATE: AppState;
// implementation if necessary     
function createNewState<KAction extends keyof AppState, KActionProp extends keyof AppState[KAction]>(state: AppState, property: [KAction, KActionProp], value: AppState[KAction][KActionProp]): AppState {
    return Object.assign({ ...state }, {
        [property[0]]: Object.assign({ ...state[property[0]] }, {
            [property[1]]: value,
        })
    });
}
function myReducer(state: AppState = INITIAL_STATE, a: Action): AppState {
    switch (a.type) {
        case 'SET_PROPERTY_VALUE': {
            const action = a as SetPropertyValueAction<never, never>; //  we don't know the actual type, never will have to do

            return createNewState(state, action.payload.property, action.payload.value);
        }
    }
    return state;
}

这篇关于TypeScript:如何强制转换通用对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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