I have a tagged/discriminated union in typescript that defines several input types.
Now, when I write a helper function with a exhaustive switch based on the type field (the discriminator) typescript is incorrectly narrowing the final type to any (instead of the expected never).
Exhaustive means that I handle all the cases and in the default branch I put an assertion of something that should never be reached. Is in that last default part where typescript is incorrectly inferring the input to be any (when it should be never)
Here is the complete code for reference:
type inputType = {
type: "select";
source: "notes";
folder: string;
} | {
type: "tag";
exclude?: string | undefined;
} | {
type: "slider";
min: number;
max: number;
} | {
type: "note";
folder: string;
} | {
type: "folder";
} | {
type: "dataview";
query: string;
} | {
type: "number" | "text" | "date" | "time" | "datetime" | "textarea" | "toggle" | "email" | "tel";
} | {
type: "select";
source: "fixed";
options: {
value: string;
label: string;
}[];
} | {
type: "multiselect";
source: "notes";
folder: string;
} | {
type: "multiselect";
source: "fixed";
multi_select_options: string[];
allowUnknownValues: boolean;
} | {
type: "multiselect";
source: "dataview";
query: string;
allowUnknownValues: boolean;
} | {
type: "document_block";
body: string;
}
function absurd<T>(_:never):T{
throw new Error('Absurd!')
}
export function requiresListOfStrings(input: inputType): boolean {
switch (input.type) {
case "multiselect":
case "tag":
return true;
case "select":
case "dataview":
case "note":
case "folder":
case "slider":
case "document_block":
case "number":
case "text":
case "date":
case "time":
case "datetime":
case "textarea":
case "toggle":
case "email":
case "tel":
return false;
default:
return absurd(input.type); // Here is the error
}
}
And this is the error typescript is reporting:
Argument of type 'any' is not assignable to parameter of type 'never'.
Property 'type' does not exist on type 'never'.
I tested this in 5.4 and 5.5 and fails in both.
here is a playground link in case it helps