Skip to content

Commit 7390d6c

Browse files
unionalmweststrate
andauthored
fix: improve higher order type inference for WritableDraft (#1205)
* fix: improve higher order type inference for WritableDraft * fix: support tuples with spread in WritableDraft --------- Co-authored-by: Michel Weststrate <mweststrate@gmail.com>
1 parent 5155a33 commit 7390d6c

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

__tests__/produce.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,24 @@ it("allows for mixed property value types", () => {
771771
})
772772
})
773773

774+
it("allows higher order type inference", () => {
775+
function _test<A>() {
776+
type S = {prop: A | undefined}
777+
produce(
778+
draft => {
779+
draft.prop = undefined
780+
},
781+
{prop: undefined} as S
782+
)
783+
}
784+
})
785+
786+
it("supports tuples with spread", () => {
787+
type State = [boolean, ...number[]]
788+
const foo = (x: State) => x
789+
produce<State>(x => foo(x))
790+
})
791+
774792
it("#877 - produce with typed state generic requires initial state", () => {
775793
const reducerNoInitial = produce<{count: number}, [{type: "inc"}]>(
776794
(draft, action: {type: "inc"}) => {

src/types/types-external.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,25 @@ type WeakReferences = IfAvailable<WeakMap<any, any>> | IfAvailable<WeakSet<any>>
3030

3131
export type WritableDraft<T> = T extends any[]
3232
? number extends T["length"]
33-
? Draft<T[number]>[]
33+
? IsPlainArray<T> extends true
34+
? Draft<T[number]>[]
35+
: WritableNonArrayDraft<T>
3436
: WritableNonArrayDraft<T>
3537
: WritableNonArrayDraft<T>
3638

39+
/**
40+
* Distinguishes plain array types (`number[]`, `readonly string[]`, etc.) from
41+
* tuple types — including variadic tuples like `[boolean, ...number[]]` — whose
42+
* `length` is also `number` but must not be widened to `Element[]`.
43+
*/
44+
type IsPlainArray<T extends readonly any[]> = T extends readonly (infer U)[]
45+
? U[] extends T
46+
? true
47+
: false
48+
: false
49+
3750
type WritableNonArrayDraft<T> = {
38-
-readonly [K in keyof T]: T[K] extends infer V
51+
-readonly [K in keyof T]: {_: T[K]} extends {_: infer V}
3952
? V extends object
4053
? Draft<V>
4154
: V

0 commit comments

Comments
 (0)