Reputation: 27
Im trying to create a function of which one argument is dependant on the other. I can not make it work and it's starting to drive me crazy. Here's what i'm trying to do:
export interface LaneLayout {
i: number;
x: number;
y: number;
w: number;
h: number;
lane_content: string;
project_id: number;
}
export type Action = "modify" | "create";
export type ModifiedLaneLayout = Omit<
LaneLayout,
"project_id" | "lane_content"
>;
export type CreatedLaneLayout = Pick<LaneLayout, "x" | "y">;
export type LayoutType<T extends Action> = T extends "modify"
? ModifiedLaneLayout
: T extends "create"
? CreatedLaneLayout
: never;
export function modifyBox<K extends Action>(
action: K,
layout: LayoutType<K>
): void {
if (action === "modify") {
layout.h; // property h should exist here
} else {
layout.h // property h should not exist here
}
}
In the function, it seems that regardless of the value of action, the type of the layout argument is always CreatedLaneLayout and property h doesn't exist in both cases of the if-statement. What am I missing here?
Upvotes: 0
Views: 25
Reputation: 856
You'll need to join both arguments together into one object (and also modifyBox will stop being a generic function after this):
type ModifyBoxArgument
= {action: 'create'; layout: CreatedLaneLayout}
| {action: 'modify'; layout: ModifiedLaneLayout}
export function modifyBox(arg: ModifyBoxArgument): void {
if (arg.action === "modify") {
arg.layout.h; // property h should exist here
} else {
arg.layout.h // property h should not exist here
}
}
But remember that you cannot destructure arg
until you're inside if
's body (or in the else
section), or it will prevent the compiler from tracking the dependency between action
and layout
types.
Upvotes: 1