One way to handle this is to cast the property so TypeScript knows what type it should be.
let userlist:User[] = <User[]>action.payload;
If that doesn't work then you can cast to any and then to the type.
let userlist:User[] = <User[]><any>action.payload;
But that's not really using the type system to it's full potential, and isn't very nice code.
Rather than forcing the type to be a specific type using a cast, it'd be nice if we could tell the type system how to figure out what type it is.
So ... it sounds like you want Type Guards.
https://www.typescriptlang.org/docs/handbook/advanced-types.html
(Look for the section titled 'User-Defined Type Guards')
You can make a special function that tests if an object is of a certain type.
That function returns a bool, true for a match, false for no match.
When you test a variable using that function in your code TypeScript recognises the type test and changes the type of that variable to match the tested type.
So you end up with code like this:
if (isUserAction(action)) {
let user: IUser = action.Payload;
}
I couldn't get them working with the exact object layout you have, but I made a similar example with a few tweaks that allow the type guards to work.
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
Output:
user: foo
users: bar
users: baz
The documentation is very good and has lots of detail to teach you about this features, and all the rest.
Another good source is basarat.gitbooks.io.