I am trying to use conditional type to link two parameters in a function, but I couldn't sort out to link 2 parameters when defining a function. Below is the simplified sample or the live version.
type Circle = { type: "circle"; data: { radius: number } };
type Rect = { type: "rect"; data: { width: number; height: number } };
type DefinedShape = Circle | Rect;
type FilterShapeByType<Shape, Type> = Shape extends { type: Type }
? Shape
: never;
type DrawShape = <T extends DefinedShape["type"]>(
type: T,
data: FilterShapeByType<DefinedShape, T>["data"]
) => void;
let drawShape1: DrawShape = () => {};
drawShape1("rect", { height: 12, width: 22 }); // pass
drawShape1("rect", { height: 12, width: 22, radius: 23 }); // failed, radius is not defined
drawShape1("circle", { radius: 12 }); // pass
drawShape1("circle", { radius: 12, len: 23 }); // failed, len is not defined
const drawShape2: DrawShape = (type, data) => {
switch (type) {
case "circle":
console.log(data.radius); // failed, Property 'radius' does not exist on type '(FilterShapeByType<Circle, T> | FilterShapeByType<Rect, T>)["data"]'.
break;
case "rect":
console.log(data.height, data.width);
break;
}
};
the original goal is to link the two parameters in DrawShape function, meaning when type is circle, the data should be {radius: number}. I use the conditional type FilterShapeByType to sort it out.
All good before I try to define a function drawShape2. I am expecting when I use switch for the type for circle, the typescript should smart enough to assume data should be the Circle['data'], however it didn't. Wondering is there easy to make it automatically?