From 8ee336582aafc3b902829de91ea4bfef72d8eada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E5=BB=B7=E5=AE=89?= <73953029+nrps9909@users.noreply.github.com> Date: Fri, 28 Aug 2026 17:00:13 +0800 Subject: [PATCH] fix: preserve branded primitive values --- src/interface.ts | 5 ++++- tests/nameTypeCheck.test.tsx | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/interface.ts b/src/interface.ts index 0946160f..426fa71c 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -243,8 +243,11 @@ export interface InternalHooks { getInitialValue: (namePath: InternalNamePath) => StoreValue; } +type Primitive = string | number | bigint | boolean | symbol | null | undefined; + /** Only return partial when type is not any */ -export type RecursivePartial = T extends Date | RegExp | Function | Map | Set +export type RecursivePartial = T extends + Primitive | Date | RegExp | Function | Map | Set ? T : T extends (infer U)[] ? RecursivePartial[] diff --git a/tests/nameTypeCheck.test.tsx b/tests/nameTypeCheck.test.tsx index 26c71daa..430cba8e 100644 --- a/tests/nameTypeCheck.test.tsx +++ b/tests/nameTypeCheck.test.tsx @@ -2,7 +2,11 @@ import React, { useMemo } from 'react'; import { render } from '@testing-library/react'; import Form, { Field, List } from '../src'; -import type { FormInstance, NamePath } from '../src/interface'; +import type { FormInstance, NamePath, RecursivePartial } from '../src/interface'; + +type Equal = + (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? true : false; +type Expect = T; describe('nameTypeCheck', () => { it('typescript', () => { @@ -23,6 +27,11 @@ describe('nameTypeCheck', () => { type SetFieldsValueParam = Parameters['setFieldsValue']>[0]; + type DomainId = string & { + readonly __nominal: unique symbol; + }; + type BrandedPartial = RecursivePartial<{ id: DomainId }>; + const nullableListAsNull: SetFieldsValueParam = { nullableList: null }; const nullableListAsArray: SetFieldsValueParam = { nullableList: ['bamboo'] }; const nullableObjectListAsNull: SetFieldsValueParam = { nullableObjectList: null }; @@ -39,6 +48,10 @@ describe('nameTypeCheck', () => { const optionalListAsPartial: SetFieldsValueParam = { strictList: [{ age: '18' }], }; + const brandedValue: BrandedPartial = { + id: 'domain-id' as DomainId, + }; + const brandedTypeCheck: Expect> = true; const useGenericSetter = () => { const [form] = Form.useForm(); return (values: Partial) => form.setFieldsValue(values);