UNPKG

@payfit/unity-components

Version:

57 lines (56 loc) 2.93 kB
/** * Mirrors a form submit value shape while allowing each nested value to be * initialized with `undefined`. * * TanStack Form `defaultValues` often describe an incomplete form state: a * field can start empty even when the validated submit payload requires it. * This type keeps the submit schema as the source of truth while making those * empty initial field values type-safe. */ type DeepAllowUndefined<T> = T extends Array<infer Item> ? Array<DeepAllowUndefined<Item>> | undefined : T extends object ? { [K in keyof T]: DeepAllowUndefined<T[K]> | undefined; } : T | undefined; /** * Makes one path required again after `DeepAllowUndefined` allowed `undefined` * throughout the value shape. * * Paths are expressed as tuples of object keys. Use `number` to target every * item in an array, for example `['answers', number, 'questionId']`. */ type KeepRequiredAtPath<T, Path extends readonly unknown[]> = Path extends [] ? Exclude<T, undefined> : T extends Array<infer Item> ? Path extends [number, ...infer Rest extends readonly unknown[]] ? Array<KeepRequiredAtPath<Item, Rest>> : T : Path extends [ infer Key extends keyof T, ...infer Rest extends readonly unknown[] ] ? Omit<T, Key> & { [K in Key]-?: KeepRequiredAtPath<Exclude<T[Key], undefined>, Rest>; } : T; /** * Applies `KeepRequiredAtPath` to several paths. * * This is useful when some containers or technical identifiers must always be * present in `defaultValues`, while regular user-input fields can still start * as `undefined`. */ type KeepRequiredAtPaths<T, Paths extends ReadonlyArray<readonly unknown[]>> = Paths extends readonly [ infer Path extends readonly unknown[], ...infer Rest extends ReadonlyArray<readonly unknown[]> ] ? KeepRequiredAtPaths<KeepRequiredAtPath<T, Path>, Rest> : T; /** * Helper type for TanStack Form `defaultValues`. * * It starts from the final submit values, allows `undefined` throughout the * default form state, then re-requires the paths listed in `RequiredPaths`. * * We created it to avoid maintaining a separate default-values type or using * unsafe casts when default values are intentionally less complete than the * validated submit payload. */ export type TanstackFormDefaultValues<SubmitValues, RequiredPaths extends ReadonlyArray<readonly unknown[]> = []> = KeepRequiredAtPaths<DeepAllowUndefined<SubmitValues>, RequiredPaths>; /** * Runtime no-op used to type-check TanStack Form default values. * * The function returns the provided value unchanged. Its purpose is to make * object literals satisfy `TanstackFormDefaultValues` at compile time while * keeping call sites compact. */ export declare function tanstackFormDefaultValues<SubmitValues, RequiredPaths extends ReadonlyArray<readonly unknown[]> = []>(value: TanstackFormDefaultValues<SubmitValues, RequiredPaths>): KeepRequiredAtPaths<DeepAllowUndefined<SubmitValues>, RequiredPaths>; export {};