Repository: pmndrs/zustand
File: src/middleware/devtools.ts (TypeScript)

Code before:
  : T extends [unknown, unknown]
  ? T
  : T extends [unknown, unknown?]
  ? T
  : T extends [unknown?, unknown?]
  ? T
  : T extends [infer A0, infer A1, ...unknown[]]
  ? [A0, A1]
  : T extends [infer A0, (infer A1)?, ...unknown[]]
  ? [A0, A1?]
  : T extends [(infer A0)?, (infer A1)?, ...unknown[]]
  ? [A0?, A1?]
  : never

type WithDevtools<S> = Write<Cast<S, object>, StoreDevtools<S>>

type StoreDevtools<S> = S extends {
  setState: (...a: infer A) => infer Sr
}
  ? {
      setState(
        ...a: [
          ...a: TakeTwo<A>,
          actionType?: string | { type: unknown; payload?: unknown }
        ]
      ): Sr
    }
  : never

export interface DevtoolsOptions {
  enabled?: boolean
  anonymousActionType?: string
  name?: string
  serialize?:
    | boolean
    | {
        date?: boolean
        regex?: boolean
        undefined?: boolean
        nan?: boolean
        infinity?: boolean
        error?: boolean
        symbol?: boolean
        map?: boolean
        set?: boolean
      }
}

type Devtools = <
  T extends object,
  Mps extends [StoreMutatorIdentifier, unknown][] = [],

Review comment (suggestion):
I think the problem is that the following does not compile...

```ts
import create from "zustand"
import { devtools } from "zustand/middleware"

interface BearState {
  bears: number
  increase: (by: number) => void
}

const useBearStore = create<BearState>()(devtools((set) => ({
  bears: 0,
  increase: by => set(
    (state) => ({ bears: state.bears + by }),
    false,
    { type: "increase", by }
//                      ~~[1]
  ),
})))

// [1]:
// Argument of type '{ type: string; by: number; }' is not assignable to parameter of type 'string | { type: unknown; } | undefined'.
//   Object literal may only specify known properties, and 'by' does not exist in type '{ type: unknown; }'.
```

This is because of TypeScript's "excess property checks", the correct way to fix is to tell typescript that the type of `action` is not `{ type: unknown }` but rather `extends { type: unknown }` like so...

```suggestion
      setState<A extends string | { type: unknown }>(
        ...a: [...a: TakeTwo<A>, actionType?: string | { type: unknown }]
        ...a: [
          ...a: TakeTwo<A>,
          action?: A
        ]
      ): Sr
```


Another way to fix is like this...

```ts
setState(
  ...a: [...a: TakeTwo<A>, actionType?: string | { type: unknown }]
  ...a: [
    ...a: TakeTwo<A>,
    action?: string | { type: unknown } & { [_ in string]: unknown }
  ]
): Sr
```

But this seems a little less correct and in general it's good to stay away from index signatures (ie `{ [_ in string]: unknown }`).

And the current fix `{ type: unknown, payload?: unknown }` doesn't make the cut because it doesn't really solve the actual problem showed above, `{ type: "increase", by }` should also be assignable to `action` parameter.

Code after:
  : T extends [unknown, unknown]
  ? T
  : T extends [unknown, unknown?]
  ? T
  : T extends [unknown?, unknown?]
  ? T
  : T extends [infer A0, infer A1, ...unknown[]]
  ? [A0, A1]
  : T extends [infer A0, (infer A1)?, ...unknown[]]
  ? [A0, A1?]
  : T extends [(infer A0)?, (infer A1)?, ...unknown[]]
  ? [A0?, A1?]
  : never

type WithDevtools<S> = Write<Cast<S, object>, StoreDevtools<S>>

type StoreDevtools<S> = S extends {
  setState: (...a: infer Sa) => infer Sr
}
  ? {
      setState<A extends string | { type: unknown }>(
        ...a: [...a: TakeTwo<Sa>, action?: A]
      ): Sr
    }
  : never

export interface DevtoolsOptions {
  enabled?: boolean
  anonymousActionType?: string
  name?: string
  serialize?:
    | boolean
    | {
        date?: boolean
        regex?: boolean
        undefined?: boolean
        nan?: boolean
        infinity?: boolean
        error?: boolean
        symbol?: boolean
        map?: boolean
        set?: boolean
      }
}

type Devtools = <
  T extends object,
  Mps extends [StoreMutatorIdentifier, unknown][] = [],
  Mcs extends [StoreMutatorIdentifier, unknown][] = []
>(
  initializer: StateCreator<T, [...Mps, ['zustand/devtools', never]], Mcs>,