For context, here is my schema expressed in ts types for clarity js { engine_type: "Petrol" | "Petrol-LPG" | "Diesel" | "Mild Hybrid" | "Hybrid" | "Plug-in Hybrid"; manufacturer: string; model: string; variant: string; price: number; co2_min?: number | null | undefined; co2_max?: number | null | undefined; engine_displacement?: number | null | undefined; fuel_economy_min?: number | null | undefined; fuel_economy_max?: number | null | undefined; hp?: number | null | undefined; url?: string | null | undefined; } | { engine_type: "Electric"; manufacturer: string; model: string; variant: string; price: number; battery_capacity?: number | null | undefined; energy_consumption?: number | ... 1 more ... | undefined; battery_range?: number | ... 1 more ... | undefined; hp?: number | ... 1 more ... | undefined; url?: string | ... 1 more ... | undefined; } In my form the default value of engine_type is 'Petrol", so the 1st variant is used for type checking. I am using the form.Subscribe HOC to show only the relavant fields based on the engine_type. The type error manifests in the electric car only fields. Any idea how to get rid of the type error without casting?
#tanstack form type errors with a zod discriminated union
9 messages · Page 1 of 1 (latest)
how do you give the form the default values?
what might be happening is two things:
- You're giving the defaultValues directly. TypeScript won't know it can be a union in this case, so it will complain.
- You're assigning
defaultValuesexternally with the correct type. However, TypeScript thinks that, sincedefaultValuesis never reassigned, it is only part of the union. It's a problem that has been around for a while, and neithersatisfiesorascan properly solve it.
type Animal = Dog | Cat;
const value: Animal = cat();
// ^? Cat
// this also won't do, not type safe
const value = cat() as Animal;
// this doesn't change the type
const value = cat() satisfies Animal;
// ^? Cat
// this does what you expect
const value = cat() satisfies Animal as Animal;
// Alternative approach
function identity<T>(obj: T): T { return T; }
const value = identity<Animal>(cat())
for a quick check, satisfies X as X should "solve the types"
okay, yeah then it was that issue
as general note, you'll often see this problem pop up with string unions and assigning an initial one. An identity function never hurts to be around for type safety
An example from our workplace:
export function oneof<T = never>(value: T): T { return T; }