diff --git a/.github/workflows/test-multiple-versions.yml b/.github/workflows/test-multiple-versions.yml index c9a07e7fb0..198db40f41 100644 --- a/.github/workflows/test-multiple-versions.yml +++ b/.github/workflows/test-multiple-versions.yml @@ -39,7 +39,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '14' cache: yarn - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - run: yarn install --frozen-lockfile --check-files diff --git a/.github/workflows/test-old-typescript.yml b/.github/workflows/test-old-typescript.yml new file mode 100644 index 0000000000..ecf2242e95 --- /dev/null +++ b/.github/workflows/test-old-typescript.yml @@ -0,0 +1,43 @@ +name: Test Old TypeScript + +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize] + +jobs: + test_matrix: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + typescript: + - 4.8.4 + - 4.7.4 + - 4.6.4 + - 4.5.5 + - 4.4.4 + - 4.3.5 + - 4.2.3 + - 4.1.5 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '14' + cache: yarn + - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* + - run: yarn install --frozen-lockfile --check-files + - run: yarn build + - name: Patch for Old TS + run: | + sed -i~ "s/\/\/ @ts-expect-error.*\[LATEST-TS-ONLY\]//" tests/*.tsx + sed -i~ "s/\"exactOptionalPropertyTypes\": true,//" tsconfig.json + sed -i~ "s/\"zustand\": \[\"\.\/src\/index\.ts\"\],/\"zustand\": [\".\/dist\/index.d.ts\"],/" tsconfig.json + sed -i~ "s/\"zustand\/\*\": \[\"\.\/src\/\*\.ts\"\]/\"zustand\/*\": [\".\/dist\/*.d.ts\"]/" tsconfig.json + sed -i~ "s/\"include\": .*/\"include\": [\"src\/types.d.ts\", \"dist\/**\/*\", \"tests\/**\/*\"],/" tsconfig.json + - name: Test ${{ matrix.typescript }} + run: | + yarn add -D typescript@${{ matrix.typescript }} + yarn tsc --noEmit diff --git a/src/middleware/devtools.ts b/src/middleware/devtools.ts index 558a693658..287b7a2b71 100644 --- a/src/middleware/devtools.ts +++ b/src/middleware/devtools.ts @@ -85,18 +85,19 @@ type Message = { state?: any } +type Cast = T extends U ? T : U type Write = Omit & U -type TakeTwo = T extends [] +type TakeTwo = T extends { length: 0 } ? [undefined, undefined] - : T extends [unknown] - ? [...a0: T, a1: undefined] - : T extends [unknown?] - ? [...a0: T, a1: undefined] - : T extends [unknown, unknown] + : T extends { length: 1 } + ? [...a0: Cast, a1: undefined] + : T extends { length: 0 | 1 } + ? [...a0: Cast, a1: undefined] + : T extends { length: 2 } ? T - : T extends [unknown, unknown?] + : T extends { length: 1 | 2 } ? T - : T extends [unknown?, unknown?] + : T extends { length: 0 | 1 | 2 } ? T : T extends [infer A0, infer A1, ...unknown[]] ? [A0, A1] diff --git a/src/middleware/immer.ts b/src/middleware/immer.ts index 880367793e..ee661595bc 100644 --- a/src/middleware/immer.ts +++ b/src/middleware/immer.ts @@ -18,11 +18,11 @@ declare module '../vanilla' { } type Write = Omit & U -type SkipTwo = T extends [] +type SkipTwo = T extends { length: 0 } ? [] - : T extends [unknown] + : T extends { length: 1 } ? [] - : T extends [unknown?] + : T extends { length: 0 | 1 } ? [] : T extends [unknown, unknown, ...infer A] ? A diff --git a/src/vanilla.ts b/src/vanilla.ts index 65cc64537d..13791dbb08 100644 --- a/src/vanilla.ts +++ b/src/vanilla.ts @@ -14,7 +14,9 @@ export interface StoreApi { type Get = K extends keyof T ? T[K] : F -export type Mutate = Ms extends [] +export type Mutate = number extends Ms['length' & keyof Ms] + ? S + : Ms extends [] ? S : Ms extends [[infer Mi, infer Ma], ...infer Mrs] ? Mutate[Mi & StoreMutatorIdentifier], Mrs> diff --git a/tests/types.test.tsx b/tests/types.test.tsx index 559687867f..704724114f 100644 --- a/tests/types.test.tsx +++ b/tests/types.test.tsx @@ -106,9 +106,9 @@ it('should have correct (partial) types for setState', () => { const store = create((set) => ({ count: 0, - // @ts-expect-error we shouldn't be able to set count to undefined + // @ts-expect-error we shouldn't be able to set count to undefined [LATEST-TS-ONLY] a: () => set(() => ({ count: undefined })), - // @ts-expect-error we shouldn't be able to set count to undefined + // @ts-expect-error we shouldn't be able to set count to undefined [LATEST-TS-ONLY] b: () => set({ count: undefined }), c: () => set({ count: 1 }), })) @@ -124,9 +124,9 @@ it('should have correct (partial) types for setState', () => { store.setState({}) store.setState((previous) => previous) - // @ts-expect-error type undefined is not assignable to type number + // @ts-expect-error type undefined is not assignable to type number [LATEST-TS-ONLY] store.setState({ count: undefined }) - // @ts-expect-error type undefined is not assignable to type number + // @ts-expect-error type undefined is not assignable to type number [LATEST-TS-ONLY] store.setState((state) => ({ ...state, count: undefined })) })