Reputation: 1763
Given:
export type CommandsTypes = {
"test-command": {
propA: string;
propB: number;
};
"test-command2": {
propC: string;
propD: number;
};
};
export type Command<K extends keyof CommandsTypes> = {
type: K;
payload: CommandsTypes[K];
};
export type AnyCommand = Command<keyof CommandsTypes>;
Why does the following not type-narrow as expected:
function handle(command: AnyCommand) {
if (command.type === "test-command") {
// I would expect the type of command at this point to be
// Command<"test-command">
// But its not?
}
}
Any ideas why Typescript isnt able to narrow the AnyCommand
type above to
Command<"test-command">
?
Upvotes: 1
Views: 49
Reputation: 249506
Command<keyof CommandTypes>
will be equivalent to { type: keyof CommandTypes, payload :CommandTypes[keyof CommandTypes] }
basically this would mean you could pair any type with any payload, which is not what you want.
You would want to build a discriminated union. Todo this we can use the distributive behavior of conditional types which will apply a type transformation over each member of the union of keys
export type AnyCommandHelper<T extends keyof CommandsTypes> =
T extends keyof CommandsTypes? Command<T>: never
export type AnyCommand = AnyCommandHelper<keyof CommandsTypes>;
Upvotes: 1