From 8e724e372c95d9bb20d8a043f8c32babd3e6d109 Mon Sep 17 00:00:00 2001 From: unional Date: Fri, 10 Apr 2026 09:10:36 -0700 Subject: [PATCH 1/2] fix: improve higher order type inference for WritableDraft --- __tests__/produce.ts | 12 ++++++++++++ src/types/types-external.ts | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/__tests__/produce.ts b/__tests__/produce.ts index c3913873..a7667b13 100644 --- a/__tests__/produce.ts +++ b/__tests__/produce.ts @@ -758,3 +758,15 @@ it("allows for mixed property value types", () => { } }) }) + +it("allows higher order type inference", () => { + function _test() { + type S = {prop: A | undefined} + produce( + draft => { + draft.prop = undefined + }, + {prop: undefined} as S + ) + } +}) diff --git a/src/types/types-external.ts b/src/types/types-external.ts index d3e7df2c..16db28a8 100644 --- a/src/types/types-external.ts +++ b/src/types/types-external.ts @@ -37,7 +37,7 @@ export type WritableDraft = T extends any[] : WritableNonArrayDraft type WritableNonArrayDraft = { - -readonly [K in keyof T]: T[K] extends infer V + -readonly [K in keyof T]: {_: T[K]} extends {_: infer V} ? V extends object ? Draft : V From 3c296633d5128f6bf8dd00b92632cb1a0b9fa30c Mon Sep 17 00:00:00 2001 From: unional Date: Fri, 10 Apr 2026 09:10:36 -0700 Subject: [PATCH 2/2] fix: support tuples with spread in WritableDraft --- __tests__/produce.ts | 6 ++++++ src/types/types-external.ts | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/__tests__/produce.ts b/__tests__/produce.ts index a7667b13..8da9c2b2 100644 --- a/__tests__/produce.ts +++ b/__tests__/produce.ts @@ -770,3 +770,9 @@ it("allows higher order type inference", () => { ) } }) + +it("supports tuples with spread", () => { + type State = [boolean, ...number[]] + const foo = (x: State) => x + produce(x => foo(x)) +}) diff --git a/src/types/types-external.ts b/src/types/types-external.ts index 16db28a8..5c98be89 100644 --- a/src/types/types-external.ts +++ b/src/types/types-external.ts @@ -32,10 +32,23 @@ type WeakReferences = IfAvailable> | IfAvailable> export type WritableDraft = T extends any[] ? number extends T["length"] - ? Draft[] + ? IsPlainArray extends true + ? Draft[] + : WritableNonArrayDraft : WritableNonArrayDraft : WritableNonArrayDraft +/** + * Distinguishes plain array types (`number[]`, `readonly string[]`, etc.) from + * tuple types — including variadic tuples like `[boolean, ...number[]]` — whose + * `length` is also `number` but must not be widened to `Element[]`. + */ +type IsPlainArray = T extends readonly (infer U)[] + ? U[] extends T + ? true + : false + : false + type WritableNonArrayDraft = { -readonly [K in keyof T]: {_: T[K]} extends {_: infer V} ? V extends object