Reputation: 115
Given some types that looks like this
type Priority = "HIGH" | "MED" | "LOW";
type Task = {
title: string;
desc: string;
priority: Priority;
}
interface Edit<T> {
param: T;
change: T extends "title" | "desc"
? string
: T extends "priority"
? Priority
: never;
}
export type ParamsType<T> = T extends "add"
? Add
: T extends "help"
? Help
: T extends "edit"
? Edit<keyof Task>
: never;
used in a function like this
exec<T extends Params>(command: T, args: ParamsType<T>) {
// console.log(this);
switch (command) {
case "add":
// call add
break;
case "edit":
// call edit
break;
}
}
How can I get type inference for change based on a call like this?
schedule.exec("edit", {param: "priority", change: "notintype"}
I am getting type inference based on the value passed as the first parameter so how could I adapt that to getting the change to be typed as well?
Upvotes: 1
Views: 47
Reputation: 15106
You can probably get the behavior you want by rewriting Edit
to distribute over unions, so Edit<'title' | 'desc' | 'priority'>
is evaluated as Edit<'title'> | Edit<'desc'> | Edit<'priority'>
, which will provide the proper type checking.
To have Edit
distribute over unions, you can convert it to a type definition and introduce a dummy conditional (see docs):
type Edit<T> = T extends any ? {
param: T;
change: T extends "title" | "desc"
? string
: T extends "priority"
? Priority
: never;
} : never
This will allow calls like
schedule.exec("edit", {param: "priority", change: "HIGH"})
schedule.exec("edit", {param: "title", change: "Title"})
but fail with a type error on
schedule.exec("edit", {param: "priority", change: "notintype"})
Upvotes: 1