2017-04-11 84 views
0

我使用nrgx /存储和下面的示例应用程序,我使用类强类型我的动作像打字稿 - 指定类型的多种类型

export const ActionTypes ={ 
    SET_ACTIVE_USER: type('[UserState] Set Active User'), 
    SET_USERLIST: type('[UserState] Set Userlist') 
}; 

export class SetActiveUserAction implements Action { 
    type = ActionTypes.SET_ACTIVE_USER; 
    constructor(public payload:User){} 
} 

export class SetUserlistAction implements Action { 
    type = ActionTypes.SET_USERLIST; 
    constructor(public payload:User[]){} 
} 

export type Actions 
    = SetActiveUserAction 
    | SetUserlistAction 

我现在正在为一个导出变量在我的减速机中输入问题。由于导出操作的类型可以是用户或用户的[],它不会让我分配用户列表:用户[]它(我想使用数组方法,如的forEach)来处理这个

export function reducer(state = INITIAL_STATE, action: userAction.Actions): State { 

    switch (action.type) { 
     case userAction.ActionTypes.SET_USERLIST: { 

      let userlist:User[] = action.payload <-------Type Issue 

      return tassign(state, { userlist: action.payload }) 
     } 

     default: { 
      return state 
     } 
    } 
} 
+0

https://github.com/ngrx/example-app/issues/127 – cartant

回答

2

的一种方式是投射属性,以便TypeScript知道它应该是什么类型。

let userlist:User[] = <User[]>action.payload; 

如果不工作,那么你可以转换为any再到类型。

let userlist:User[] = <User[]><any>action.payload; 

但是,这不是真的使用类型系统来充分发挥其潜力,而且不是很好的代码。

如果我们可以告诉类型系统如何确定它是什么类型,那么不是强制类型成为使用类型转换的特定类型。

所以...这听起来像你想要的类型近卫。

https://www.typescriptlang.org/docs/handbook/advanced-types.html
(查找标题为“用户定义类型卫队)

您可以用来测试对象是否是某种类型的特殊功能。
该函数返回一个布尔值,对于匹配返回true,对于不匹配返回false。
在代码中使用该函数测试变量时TypeScript识别类型测试并更改该变量的类型以匹配测试类型。

所以你最终像这样的代码:

if (isUserAction(action)) { 
    let user: IUser = action.Payload; 
} 

我不能让他们跟你有确切的对象布局工作,但我做了一些调整,允许类卫士类似的例子上班。

enum ActionType { User = 1, Users = 2 } 
interface IAction { Type: ActionType; } 
interface IUser { Name: string; } 

class Action<T> implements IAction { 
    public Type: ActionType; 
    public Payload: T; 

    constructor(type: ActionType, payload: T) { 
     this.Type = type; 
     this.Payload = payload; 
    } 
} 

class UserAction extends Action<IUser> { 
    constructor(payload?: IUser) { 
     super(ActionType.User, payload); 
    } 
} 

class UsersAction extends Action<IUser[]> { 
    constructor(payload?: IUser[]) { 
     super(ActionType.Users, payload); 
    } 
} 

function isUserAction(action: IAction): action is UserAction { 
    return action.Type === ActionType.User; 
} 

function isUsersAction(action: IAction): action is UsersAction { 
    return action.Type === ActionType.Users; 
} 

function processAction(action: IAction) { 
    if (isUserAction(action)) { 
     let user: IUser = action.Payload; 
     console.log(`user: ${user.Name}`); 
    } else if (isUsersAction(action)) { 
     let users: IUser[] = action.Payload; 
     for (let user of users) { 
      console.log(`users: ${user.Name}`); 
     } 
    } 
} 

processAction(new UserAction({ Name: "foo" })); 
processAction(new UsersAction([{ Name: "bar" }, { Name: "baz" }])); 

Code @ TypeScript Playground

输出:

user: foo 
users: bar 
users: baz 

documentation非常好,有很多细节教你关于这个功能,并且所有的休息。

另一个好的来源是basarat.gitbooks.io