diff --git a/deno/lib/__tests__/record.test.ts b/deno/lib/__tests__/record.test.ts index 311f805a7..734687eca 100644 --- a/deno/lib/__tests__/record.test.ts +++ b/deno/lib/__tests__/record.test.ts @@ -17,6 +17,20 @@ const recordWithLiteralKeys = z.record( ); type recordWithLiteralKeys = z.infer; +const StringBrand = z.string().brand("StringBrand"); +type StringBrand = z.infer; +const NumberBrand = z.number().brand("NumberBrand"); +type NumberBrand = z.infer; +const SymbolBrand = z.symbol().brand("SymbolBrand"); +type SymbolBrand = z.infer; + +const recordWithBrandedStringKeys = z.record(StringBrand, z.number()); +type recordWithBrandedStringKeys = z.infer; +const recordWithBrandedNumberKeys = z.record(NumberBrand, z.number()); +type recordWithBrandedNumberKeys = z.infer; +const recordWithBrandedSymbolKeys = z.record(SymbolBrand, z.number()); +type recordWithBrandedSymbolKeys = z.infer; + test("type inference", () => { util.assertEqual>(true); @@ -29,6 +43,16 @@ test("type inference", () => { recordWithLiteralKeys, Partial> >(true); + + util.assertEqual>( + true + ); + util.assertEqual>( + true + ); + util.assertEqual>( + true + ); }); test("methods", () => { diff --git a/deno/lib/types.ts b/deno/lib/types.ts index bb2f08519..d0fc3a103 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -3531,7 +3531,11 @@ export type RecordType = [ ? Record : [symbol] extends [K] ? Record - : [BRAND] extends [K] + : [string & AnyBrand] extends [K] + ? Record + : [number & AnyBrand] extends [K] + ? Record + : [symbol & AnyBrand] extends [K] ? Record : Partial>; export class ZodRecord< @@ -4904,6 +4908,9 @@ export const BRAND: unique symbol = Symbol("zod_brand"); export type BRAND = { [BRAND]: { [k in T]: true }; }; +export type AnyBrand = { + [BRAND]: any; +}; export class ZodBranded< T extends ZodTypeAny, diff --git a/src/__tests__/record.test.ts b/src/__tests__/record.test.ts index 86f60b267..14254bbef 100644 --- a/src/__tests__/record.test.ts +++ b/src/__tests__/record.test.ts @@ -16,6 +16,20 @@ const recordWithLiteralKeys = z.record( ); type recordWithLiteralKeys = z.infer; +const StringBrand = z.string().brand("StringBrand"); +type StringBrand = z.infer; +const NumberBrand = z.number().brand("NumberBrand"); +type NumberBrand = z.infer; +const SymbolBrand = z.symbol().brand("SymbolBrand"); +type SymbolBrand = z.infer; + +const recordWithBrandedStringKeys = z.record(StringBrand, z.number()); +type recordWithBrandedStringKeys = z.infer; +const recordWithBrandedNumberKeys = z.record(NumberBrand, z.number()); +type recordWithBrandedNumberKeys = z.infer; +const recordWithBrandedSymbolKeys = z.record(SymbolBrand, z.number()); +type recordWithBrandedSymbolKeys = z.infer; + test("type inference", () => { util.assertEqual>(true); @@ -28,6 +42,16 @@ test("type inference", () => { recordWithLiteralKeys, Partial> >(true); + + util.assertEqual>( + true + ); + util.assertEqual>( + true + ); + util.assertEqual>( + true + ); }); test("methods", () => { diff --git a/src/types.ts b/src/types.ts index 5aa30b900..999bfae48 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3531,7 +3531,11 @@ export type RecordType = [ ? Record : [symbol] extends [K] ? Record - : [BRAND] extends [K] + : [string & AnyBrand] extends [K] + ? Record + : [number & AnyBrand] extends [K] + ? Record + : [symbol & AnyBrand] extends [K] ? Record : Partial>; export class ZodRecord< @@ -4904,6 +4908,9 @@ export const BRAND: unique symbol = Symbol("zod_brand"); export type BRAND = { [BRAND]: { [k in T]: true }; }; +export type AnyBrand = { + [BRAND]: any; +}; export class ZodBranded< T extends ZodTypeAny,