ronantakizawa/codereview-bench huggingface dataset:
Repository: pmndrs/zustand
File: src/middleware/devtools.ts (TypeScript)

Code before:
  ? [undefined, undefined]
  : T extends [unknown]
  ? [...a0: T, a1: undefined]
  : T extends [unknown?]
  ? [...a0: T, a1: undefined]
  : 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<AT extends string | { type: unknown; [key: string]: unknown }>(
        ...a: [...a: TakeTwo<A>, action?: AT]
      ): 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 = <

Review comment (bug):
This is still incorrect, we don't need or want an index signature at all. Maybe my suggestion code snippet here https://github.com/pmndrs/zustand/pull/1183#discussion_r942852997 was confusing because of duplicate `A`s?

And also let's rename original `A` to `Sa` instead of using `AT` so that the public generic is seen as `A`.

```diff
 type StoreDevtools<S> = S extends {
-  setState: (...a: infer A) => infer Sr
+  setState: (...a: infer Sa) => infer Sr
 }
   ? {
-      setState(
+      setState<A extends string | { type: unknown }>(
-        ...a: [...a: TakeTwo<A>, actionType?: string | { type: unknown }]
+        ...a: [...a: TakeTwo<Sa>, action?: A]
       ): Sr
     }
   : never
```

Code after:
  ? [undefined, undefined]
  : T extends [unknown]
  ? [...a0: T, a1: undefined]
  : T extends [unknown?]
  ? [...a0: T, a1: undefined]
  : 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 = <
Repository: pmndrs/zustand
File: tests/middlewareTypes.test.tsx (TypeScript)

Code before:
      useBoundStore.getState().count * 2
      useBoundStore.getState().inc()
      return <></>
    }
    TestComponent
  })
})

describe('counter state spec (double middleware)', () => {
  let savedDEV: boolean
  beforeEach(() => {
    savedDEV = __DEV__
  })
  afterEach(() => {
    __DEV__ = savedDEV
  })

  it('devtools & immer', () => {
    __DEV__ = false
    const useBoundStore = create<CounterState>()(
      immer(
        devtools(
          (set, get) => ({
            count: 0,
            inc: () =>
              set((state) => {
                state.count = get().count + 1
              }),
          }),
          { name: 'prefix' }
        )
      )
    )
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.inc)()
      useBoundStore().count * 2
      useBoundStore().inc()
      useBoundStore.getState().count * 2
      useBoundStore.getState().inc()
      useBoundStore.setState({ count: 0 }, false, 'reset')
      return <></>
    }
    TestComponent
  })

  it('devtools & redux', () => {
    __DEV__ = false
    const useBoundStore = create(
      devtools(
        redux(

Review comment (suggestion):
Let's add an action with payload to this `set` call (like you did previously) as a test for types.

Code after:
      useBoundStore.getState().count * 2
      useBoundStore.getState().inc()
      return <></>
    }
    TestComponent
  })
})

describe('counter state spec (double middleware)', () => {
  let savedDEV: boolean
  beforeEach(() => {
    savedDEV = __DEV__
  })
  afterEach(() => {
    __DEV__ = savedDEV
  })

  it('immer & devtools', () => {
    __DEV__ = false
    const useBoundStore = create<CounterState>()(
      immer(
        devtools(
          (set, get) => ({
            count: 0,
            inc: () =>
              set(
                (state) => {
                  state.count = get().count + 1
                },
                false,
                { type: 'inc', by: 1 }
              ),
          }),
          { name: 'prefix' }
        )
      )
    )
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.inc)()
      useBoundStore().count * 2
      useBoundStore().inc()
      useBoundStore.getState().count * 2
      useBoundStore.getState().inc()
      useBoundStore.setState({ count: 0 }, false, 'reset')
      return <></>
    }
    TestComponent
  })

  it('devtools & redux', () => {
Repository: pmndrs/zustand
File: tests/middlewareTypes.test.tsx (TypeScript)

Code before:
        devtools(
          (set, get) => ({
            count: 0,
            inc: () =>
              set((state) => {
                state.count = get().count + 1
              }),
          }),
          { name: 'prefix' }
        )
      )
    )
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.inc)()
      useBoundStore().count * 2
      useBoundStore().inc()
      useBoundStore.getState().count * 2
      useBoundStore.getState().inc()
      useBoundStore.setState({ count: 0 }, false, 'reset')
      return <></>
    }
    TestComponent
  })

  it('immer & devtools, action with type and payload', () => {
    __DEV__ = false
    const useBoundStore = create<CounterState>()(
      immer(
        devtools(
          (set, get) => ({
            count: 0,
            inc: () =>
              set(
                (state) => {
                  state.count = get().count + 1
                },
                false,
                { type: 'inc', by: 1 }
              ),
          }),
          { name: 'prefix' }
        )
      )
    )
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.inc)()
      useBoundStore().count * 2
      useBoundStore().inc()
      useBoundStore.getState().count * 2

Review comment (suggestion):
My suggestion was to add action in the above `set` call itself xD, another test case wasn't necessary, but I think it doesn't hurt much to have one, so it's okay I guess.

Code after:
        devtools(
          (set, get) => ({
            count: 0,
            inc: () =>
              set(
                (state) => {
                  state.count = get().count + 1
                },
                false,
                { type: 'inc', by: 1 }
              ),
          }),
          { name: 'prefix' }
        )
      )
    )
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.inc)()
      useBoundStore().count * 2
      useBoundStore().inc()
      useBoundStore.getState().count * 2
      useBoundStore.getState().inc()
      useBoundStore.setState({ count: 0 }, false, 'reset')
      return <></>
    }
    TestComponent
  })

  it('devtools & redux', () => {
    __DEV__ = false
    const useBoundStore = create(
      devtools(
        redux(
          (state, action: { type: 'INC' }) => {
            switch (action.type) {
              case 'INC':
                return { ...state, count: state.count + 1 }
              default:
                return state
            }
          },
          { count: 0 }
        ),
        { name: 'prefix' }
      )
    )
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.dispatch)({ type: 'INC' })
      useBoundStore().dispatch({ type: 'INC' })
Repository: pmndrs/zustand
File: tests/middlewareTypes.test.tsx (TypeScript)

Code before:
import create, { StoreApi, UseBoundStore } from 'zustand'
import {
  combine,
  devtools,
  persist,
  redux,
  subscribeWithSelector,
} from 'zustand/middleware'
import { immer } from 'zustand/middleware/immer'
import createVanilla from 'zustand/vanilla'

type CounterState = {
  count: number
  inc: () => void
}

describe('counter state spec (no middleware)', () => {
  it('no middleware', () => {
    const useBoundStore = create<CounterState>((set, get) => ({
      count: 0,
      inc: () => set({ count: get().count + 1 }, false),
    }))
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.inc)()
      useBoundStore().count * 2

Review comment (suggestion):
```suggestion
import create, { StoreApi } from 'zustand'
```

Code after:
import create, { StoreApi } from 'zustand'
import {
  combine,
  devtools,
  persist,
  redux,
  subscribeWithSelector,
} from 'zustand/middleware'
import { immer } from 'zustand/middleware/immer'
import createVanilla from 'zustand/vanilla'

type CounterState = {
  count: number
  inc: () => void
}

describe('counter state spec (no middleware)', () => {
  it('no middleware', () => {
    const useBoundStore = create<CounterState>((set, get) => ({
      count: 0,
      inc: () => set({ count: get().count + 1 }, false),
    }))
    const TestComponent = () => {
      useBoundStore((s) => s.count) * 2
      useBoundStore((s) => s.inc)()
      useBoundStore().count * 2
Repository: pmndrs/zustand
File: tests/types.test.tsx (TypeScript)

Code before:
    M
  > = () => (set, get) => ({
    count: 0,
    increment: () => {
      // @ts-expect-errors
      set({ count: get().count + 1 })
    },
  })

  create<State>()(persist(foo()))
})

it('StateCreator subtyping', () => {
  interface State {
    count: number
    increment: () => void
  }

  const foo: () => StateCreator<State, []> = () => (set, get) => ({
    count: 0,
    increment: () => {
      set({ count: get().count + 1 })
    },
  })

  create<State>()(persist(foo()))

  let _testSubtyping: StateCreator<State, [['zustand/persist', unknown]]> =
    {} as StateCreator<State, []>
})


Review comment (suggestion):
So fixing the `StateCreator` subtyping no longer errors on this line as it does today... https://tsplay.dev/mq3pjw

Code after:
    State,
    M
  > = () => (set, get) => ({
    count: 0,
    increment: () => {
      set({ count: get().count + 1 })
    },
  })

  create<State>()(persist(foo()))
})

it('StateCreator subtyping', () => {
  interface State {
    count: number
    increment: () => void
  }

  const foo: () => StateCreator<State, []> = () => (set, get) => ({
    count: 0,
    increment: () => {
      set({ count: get().count + 1 })
    },
  })

  create<State>()(persist(foo()))

  const _testSubtyping: StateCreator<State, [['zustand/persist', unknown]]> =
    {} as StateCreator<State, []>
})
Repository: pmndrs/zustand
File: src/shallow.ts (TypeScript)

Code before:
function shallow<T>(objA: T, objB: T) {
  if (Object.is(objA, objB)) {
    return true
  }
  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false
  }

  if (objA instanceof Map && objB instanceof Map) {
    if (objA.size !== objB.size) return false

    for (const [key, value] of objA) {
      if (value !== objB.get(key)) {
        return false
      }
    }
    return true
  }

  if (objA instanceof Set && objB instanceof Set) {
    if (objA.size !== objB.size) return false

    for (const value of objA) {
      if (!objB.has(value)) {
        return false
      }
    }
    return true
  }

  const keysA = Object.keys(objA)
  if (keysA.length !== Object.keys(objB).length) {
    return false
  }
  for (let i = 0; i < keysA.length; i++) {
    if (
      !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||
      !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])

Review comment (suggestion):
Let's make it consistent:
```suggestion
      if (!Object.is(value, objB.get(key))) {
```

Code after:
function shallow<T>(objA: T, objB: T) {
  if (Object.is(objA, objB)) {
    return true
  }
  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false
  }

  if (objA instanceof Map && objB instanceof Map) {
    if (objA.size !== objB.size) return false

    for (const [key, value] of objA) {
      if (!Object.is(value, objB.get(key))) {
        return false
      }
    }
    return true
  }

  if (objA instanceof Set && objB instanceof Set) {
    if (objA.size !== objB.size) return false

    for (const value of objA) {
      if (!objB.has(value)) {
        return false
      }
    }
    return true
  }

  const keysA = Object.keys(objA)
  if (keysA.length !== Object.keys(objB).length) {
    return false
  }
  for (let i = 0; i < keysA.length; i++) {
    if (
      !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||
      !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])
Repository: pmndrs/zustand
File: src/middleware/persist.ts (TypeScript)

Code before:

  return stateFromStorage || configResult
}

const persistImpl: PersistImpl = (config, baseOptions) => {
  if (
    'getStorage' in baseOptions ||
    'serialize' in baseOptions ||
    'deserialize' in baseOptions
  ) {
    console.warn(
      '[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Please use `getPersistStorage` instead.'
    )
    return oldImpl(config, baseOptions)
  }
  return newImpl(config, baseOptions)
}

type Persist = <
  T,
  Mps extends [StoreMutatorIdentifier, unknown][] = [],
  Mcs extends [StoreMutatorIdentifier, unknown][] = [],
  U = T
>(
  initializer: StateCreator<T, [...Mps, ['zustand/persist', unknown]], Mcs>,
  options: PersistOptions<T, U>
) => StateCreator<T, Mps, [['zustand/persist', U], ...Mcs]>

declare module '../vanilla' {
  interface StoreMutators<S, A> {
    'zustand/persist': WithPersist<S, A>
  }
}

type Write<T, U> = Omit<T, keyof U> & U

type WithPersist<S, A> = S extends { getState: () => infer T }
  ? Write<S, StorePersist<T, A>>
  : never

type PersistImpl = <T>(
  storeInitializer: StateCreator<T, [], []>,
  options: PersistOptions<T, T>
) => StateCreator<T, [], []>

export const persist = persistImpl as unknown as Persist


Review comment (bug):
This didn't match with the spec in the doc. This should be a bug fix, but if anyone is omitting the options, tsc will complain.

Code after:

  return stateFromStorage || configResult
}

const persistImpl: PersistImpl = (config, baseOptions) => {
  if (
    'getStorage' in baseOptions ||
    'serialize' in baseOptions ||
    'deserialize' in baseOptions
  ) {
    console.warn(
      '[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Please use `storage` option instead.'
    )
    return oldImpl(config, baseOptions)
  }
  return newImpl(config, baseOptions)
}

type Persist = <
  T,
  Mps extends [StoreMutatorIdentifier, unknown][] = [],
  Mcs extends [StoreMutatorIdentifier, unknown][] = [],
  U = T
>(
  initializer: StateCreator<T, [...Mps, ['zustand/persist', unknown]], Mcs>,
  options: PersistOptions<T, U>
) => StateCreator<T, Mps, [['zustand/persist', U], ...Mcs]>

declare module '../vanilla' {
  interface StoreMutators<S, A> {
    'zustand/persist': WithPersist<S, A>
  }
}

type Write<T, U> = Omit<T, keyof U> & U

type WithPersist<S, A> = S extends { getState: () => infer T }
  ? Write<S, StorePersist<T, A>>
  : never

type PersistImpl = <T>(
  storeInitializer: StateCreator<T, [], []>,
  options: PersistOptions<T, T>
) => StateCreator<T, [], []>

export const persist = persistImpl as unknown as Persist
Repository: pmndrs/zustand
File: rollup.config.js (JavaScript)

Code before:
      esModule: false,
      outro: options.addModuleExport
        ? ';(module.exports = (exports && exports.default) || {}),\n  Object.assign(module.exports, exports)'
        : '',
    },
    external,
    plugins: [
      alias({
        entries: {
          './vanilla': 'zustand/vanilla',
        },
      }),
      resolve({ extensions }),
      replace({
        'import.meta.env?.MODE': 'process.env.NODE_ENV',
        delimiters: ['\\b', '\\b(?!(\\.|/))'],
        preventAssignment: true,
      }),
      babelPlugin(getBabelOptions({ ie: 11 })),
    ],
  }
}

function createUMDConfig(input, output, env) {
  const c = output.replace(/^dist\/umd\//, '').split(/\W/)
  const name = c.reduce((acc, itm, idx) => {
    if (idx === c.length - 1 && itm === 'index') {
      return acc
    }
    return acc + `${itm.slice(0, 1).toUpperCase()}${itm.slice(1)}`
  }, 'zustand')
  return {
    input,
    output: {
      file: `${output}.${env}.js`,
      format: 'umd',
      name,
      globals: {
        react: 'React',
        immer: 'immer',
        // FIXME not yet supported
        'use-sync-external-store/shim/with-selector':
          'useSyncExternalStoreShimWithSelector',
        'zustand/vanilla': 'zustandVanilla',
      },
    },
    external,
    plugins: [
      alias({
        entries: {
          './vanilla': 'zustand/vanilla',

Review comment (refactor):
I think you can extract the function inside `reduce`,
so that it's a named function. It can be extracted to a `const` inside this scope.

Something like:
```js
const toCamelCase = (acc, item, i) => { /* ... */ }
const name = c.reduce(toCamelCase, 'zustand')
```

Code after:
      esModule: false,
      outro: options.addModuleExport
        ? ';(module.exports = (exports && exports.default) || {}),\n  Object.assign(module.exports, exports)'
        : '',
    },
    external,
    plugins: [
      alias({
        entries: {
          './vanilla': 'zustand/vanilla',
        },
      }),
      resolve({ extensions }),
      replace({
        'import.meta.env?.MODE': 'process.env.NODE_ENV',
        delimiters: ['\\b', '\\b(?!(\\.|/))'],
        preventAssignment: true,
      }),
      babelPlugin(getBabelOptions({ ie: 11 })),
    ],
  }
}

function createUMDConfig(input, output, env) {
  let name = 'zustand'
  const fileName = output.slice('dist/umd/'.length)
  const capitalize = (s) => s.slice(0, 1).toUpperCase() + s.slice(1)
  if (fileName !== 'index') {
    name += fileName.replace(/(\w+)\W*/g, (_, p) => capitalize(p))
  }
  return {
    input,
    output: {
      file: `${output}.${env}.js`,
      format: 'umd',
      name,
      globals: {
        react: 'React',
        immer: 'immer',
        // FIXME not yet supported
        'use-sync-external-store/shim/with-selector':
          'useSyncExternalStoreShimWithSelector',
        'zustand/vanilla': 'zustandVanilla',
      },
    },
    external,
    plugins: [
      alias({
        entries: {
          './vanilla': 'zustand/vanilla',
        },
Repository: pmndrs/zustand
File: rollup.config.js (JavaScript)

Code before:
      format: 'cjs',
      esModule: false,
      outro: options.addModuleExport
        ? ';(module.exports = (exports && exports.default) || {}),\n  Object.assign(module.exports, exports)'
        : '',
    },
    external,
    plugins: [
      alias({
        entries: {
          './vanilla': 'zustand/vanilla',
        },
      }),
      resolve({ extensions }),
      replace({
        'import.meta.env?.MODE': 'process.env.NODE_ENV',
        delimiters: ['\\b', '\\b(?!(\\.|/))'],
        preventAssignment: true,
      }),
      babelPlugin(getBabelOptions({ ie: 11 })),
    ],
  }
}

function createUMDConfig(input, output, env) {
  const c = output.replace(/^dist\/umd\//, '').split(/\W/)
  const name = c.reduce((acc, itm, idx) => {
    if (idx === c.length - 1 && itm === 'index') {
      return acc
    }
    return acc + `${itm.slice(0, 1).toUpperCase()}${itm.slice(1)}`
  }, 'zustand')
  return {
    input,
    output: {
      file: `${output}.${env}.js`,
      format: 'umd',
      name,
      globals: {
        react: 'React',
        immer: 'immer',
        // FIXME not yet supported
        'use-sync-external-store/shim/with-selector':
          'useSyncExternalStoreShimWithSelector',
        'zustand/vanilla': 'zustandVanilla',
      },
    },
    external,
    plugins: [
      alias({
        entries: {

Review comment (suggestion):
I think using a longer name than `c` will be beneficial, because right now it's hard to understand.

Code after:
      format: 'cjs',
      esModule: false,
      outro: options.addModuleExport
        ? ';(module.exports = (exports && exports.default) || {}),\n  Object.assign(module.exports, exports)'
        : '',
    },
    external,
    plugins: [
      alias({
        entries: {
          './vanilla': 'zustand/vanilla',
        },
      }),
      resolve({ extensions }),
      replace({
        'import.meta.env?.MODE': 'process.env.NODE_ENV',
        delimiters: ['\\b', '\\b(?!(\\.|/))'],
        preventAssignment: true,
      }),
      babelPlugin(getBabelOptions({ ie: 11 })),
    ],
  }
}

function createUMDConfig(input, output, env) {
  let name = 'zustand'
  const fileName = output.slice('dist/umd/'.length)
  const capitalize = (s) => s.slice(0, 1).toUpperCase() + s.slice(1)
  if (fileName !== 'index') {
    name += fileName.replace(/(\w+)\W*/g, (_, p) => capitalize(p))
  }
  return {
    input,
    output: {
      file: `${output}.${env}.js`,
      format: 'umd',
      name,
      globals: {
        react: 'React',
        immer: 'immer',
        // FIXME not yet supported
        'use-sync-external-store/shim/with-selector':
          'useSyncExternalStoreShimWithSelector',
        'zustand/vanilla': 'zustandVanilla',
      },
    },
    external,
    plugins: [
      alias({
        entries: {
          './vanilla': 'zustand/vanilla',