Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
07b3377
fix(form-core): fix DeepValue from record values being wrong
LeCarbonator Jun 5, 2025
dc3d50c
chore: Merge branch upstream main
LeCarbonator Nov 6, 2025
4ae5048
fix: make deepValue union instead of intersection
LeCarbonator Nov 6, 2025
1eff811
ci: apply automated fixes and generate docs
autofix-ci[bot] Nov 6, 2025
89d1564
fix: properly analyze deep records
LeCarbonator Nov 7, 2025
4edde27
Merge branch 'deepvalue-records-fix' of github.com:TanStack/form into…
LeCarbonator Nov 7, 2025
dd2f4d0
rework DeepValue to use priority value
LeCarbonator Nov 7, 2025
d586448
chore: cleanup
LeCarbonator Nov 7, 2025
273d43b
chore(form-core): refactor util type tests
LeCarbonator Nov 9, 2025
ce35e49
Add neat-keys-invent.md
LeCarbonator Nov 9, 2025
2cd4f4a
ci: apply automated fixes and generate docs
autofix-ci[bot] Nov 9, 2025
4f2182a
chore: try different approach for less instantiations
LeCarbonator Nov 10, 2025
bd8b2ed
chore: add early union return
LeCarbonator Nov 10, 2025
ad74be5
chore: remove unnecessary branch
LeCarbonator Nov 10, 2025
e144ac5
chore: fix arrays being excluded from resolution
LeCarbonator Nov 10, 2025
6a4b770
chore: simplify some types
LeCarbonator Nov 10, 2025
25c10c1
chore: attempt 3
LeCarbonator Nov 10, 2025
a785c78
box keyof check
LeCarbonator Nov 10, 2025
9e9fd88
chore: attempt 4
LeCarbonator Nov 10, 2025
e7fbb2f
fix type errors
LeCarbonator Nov 10, 2025
4b2ced8
chore: this time for sure
LeCarbonator Nov 10, 2025
23127fb
chore: move DeepRecord into one call
LeCarbonator Nov 10, 2025
8f7913c
chore: add alias for DeepRecord
LeCarbonator Nov 10, 2025
afaf42e
chore: try string approach again
LeCarbonator Nov 11, 2025
da26a5c
reduce instantiations with early exit
LeCarbonator Nov 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/neat-keys-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@tanstack/form-core': patch
'@tanstack/react-form': patch
---

fix(form-core): fix DeepValue from record values being wrong
5 changes: 1 addition & 4 deletions packages/form-core/src/FieldGroupApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,7 @@ export class FieldGroupApi<
getFieldValue = <TField extends DeepKeys<TFieldGroupData>>(
field: TField,
): DeepValue<TFieldGroupData, TField> => {
return this.form.getFieldValue(this.getFormFieldName(field)) as DeepValue<
TFieldGroupData,
TField
>
return this.form.getFieldValue(this.getFormFieldName(field)) as never
}

/**
Expand Down
40 changes: 34 additions & 6 deletions packages/form-core/src/util-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,24 +150,52 @@ export type DeepKeysAndValuesImpl<
? DeepKeyAndValueObject<TParent, T, TAcc>
: TAcc

export type DeepRecord<T> = {
[TRecord in DeepKeysAndValues<T> as TRecord['key']]: TRecord['value']
}

/**
* The keys of an object or array, deeply nested.
*/
export type DeepKeys<T> = unknown extends T
? string
: DeepKeysAndValues<T>['key']

type ValueMatchingAccessor<
TValue extends AnyDeepKeyAndValue,
TAccessor extends string,
> = TValue extends TValue
? TAccessor extends TValue['key']
? TValue
: never
: never

type MostSpecificKey<TValue extends AnyDeepKeyAndValue> = MostSpecificKeyImpl<
TValue,
TValue
>

type LongerPrefix<K extends string> = `${K}.${string}` | `${K}[${string}`

type HasLonger<TAll extends AnyDeepKeyAndValue, K extends string> =
Extract<TAll, { key: LongerPrefix<K> }> extends never ? false : true

type MostSpecificKeyImpl<
TValue extends AnyDeepKeyAndValue,
TAll extends AnyDeepKeyAndValue,
> = TValue extends TValue
? HasLonger<TAll, TValue['key']> extends true
? never
: TValue['value']
: never

type DeepValueImpl<TValue, TAccessor extends string> = MostSpecificKey<
ValueMatchingAccessor<DeepKeysAndValues<TValue>, TAccessor>
>

/**
* Infer the type of a deeply nested property within an object or an array.
*/
export type DeepValue<TValue, TAccessor> = unknown extends TValue
export type DeepValue<TValue, TAccessor extends string> = unknown extends TValue
? TValue
: TAccessor extends DeepKeys<TValue>
? DeepRecord<TValue>[TAccessor]
? DeepValueImpl<TValue, TAccessor>
: never

/**
Expand Down
Loading
Loading