From ea5c974c73d458518aff318dbab369e506db9285 Mon Sep 17 00:00:00 2001 From: Red Huang Date: Thu, 15 Feb 2024 21:49:19 +0800 Subject: [PATCH] fix(types): mapHelpers with getters types (#2571) (#2576) --- packages/pinia/src/mapHelpers.ts | 12 ++-- packages/pinia/test-dts/index.d.ts | 4 ++ packages/pinia/test-dts/mapHelpers.test-d.ts | 67 ++++++++++++++++---- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/packages/pinia/src/mapHelpers.ts b/packages/pinia/src/mapHelpers.ts index c33d8fbffb..e20b966a79 100644 --- a/packages/pinia/src/mapHelpers.ts +++ b/packages/pinia/src/mapHelpers.ts @@ -1,4 +1,4 @@ -import type { ComponentPublicInstance } from 'vue-demi' +import type { ComponentPublicInstance, ComputedRef } from 'vue-demi' import type { _GettersTree, _Method, @@ -128,7 +128,7 @@ export function mapStores( */ export type _MapStateReturn< S extends StateTree, - G extends _GettersTree, + G extends _GettersTree | { [key: string]: ComputedRef }, Keys extends keyof S | keyof G = keyof S | keyof G, > = { // [key in keyof S | keyof G]: () => key extends keyof S @@ -145,7 +145,7 @@ export type _MapStateReturn< export type _MapStateObjectReturn< Id extends string, S extends StateTree, - G extends _GettersTree, + G extends _GettersTree | { [key: string]: ComputedRef }, A, T extends Record< string, @@ -198,7 +198,7 @@ export type _MapStateObjectReturn< export function mapState< Id extends string, S extends StateTree, - G extends _GettersTree, + G extends _GettersTree | { [key: string]: ComputedRef }, A, KeyMapper extends Record< string, @@ -235,7 +235,7 @@ export function mapState< export function mapState< Id extends string, S extends StateTree, - G extends _GettersTree, + G extends _GettersTree | { [key: string]: ComputedRef }, A, Keys extends keyof S | keyof G, >( @@ -254,7 +254,7 @@ export function mapState< export function mapState< Id extends string, S extends StateTree, - G extends _GettersTree, + G extends _GettersTree | { [key: string]: ComputedRef }, A, >( useStore: StoreDefinition, diff --git a/packages/pinia/test-dts/index.d.ts b/packages/pinia/test-dts/index.d.ts index 2e9df04353..abd9f63ca5 100644 --- a/packages/pinia/test-dts/index.d.ts +++ b/packages/pinia/test-dts/index.d.ts @@ -1,6 +1,10 @@ export * from '../dist/pinia' // export * from '../src' +export type TypeEqual = + (() => T extends Target ? 1 : 2) extends () => T extends Value ? 1 : 2 + ? true + : false export function describe(_name: string, _fn: () => void): void export function expectType(value: T): void export function expectError(value: T): void diff --git a/packages/pinia/test-dts/mapHelpers.test-d.ts b/packages/pinia/test-dts/mapHelpers.test-d.ts index 58ca94366a..c6cdd7a84c 100644 --- a/packages/pinia/test-dts/mapHelpers.test-d.ts +++ b/packages/pinia/test-dts/mapHelpers.test-d.ts @@ -1,3 +1,4 @@ +import { computed, ref } from 'vue' import { defineStore, expectType, @@ -5,9 +6,10 @@ import { mapActions, mapState, mapWritableState, + TypeEqual, } from './' -const useStore = defineStore({ +const useOptionsStore = defineStore({ id: 'name', state: () => ({ a: 'on' as 'on' | 'off', nested: { counter: 0 } }), getters: { @@ -24,6 +26,18 @@ const useStore = defineStore({ }, }) +const useSetupStore = defineStore('setupStore', () => { + const a = ref('on' as 'on' | 'off') + const upper = computed(() => a.value.toUpperCase()) + function toggleA() { + a.value = a.value === 'off' ? 'on' : 'off' + } + function setToggle(aVal: 'on' | 'off') { + return (a.value = aVal) + } + return { a, upper, toggleA, setToggle } +}) + const useCounter = defineStore({ id: 'counter', state: () => ({ n: 0 }), @@ -34,11 +48,11 @@ const useStoreDos = defineStore({ state: () => ({}), }) -type MainStore = ReturnType +type MainStore = ReturnType type DosStore = ReturnType type CounterStore = ReturnType -const computedStores = mapStores(useStore, useStoreDos, useCounter) +const computedStores = mapStores(useOptionsStore, useStoreDos, useCounter) expectType<{ nameStore: () => MainStore @@ -54,24 +68,24 @@ expectType<{ expectType<{ a: () => 'on' | 'off' upper: () => string -}>(mapState(useStore, ['a', 'upper'])) +}>(mapState(useOptionsStore, ['a', 'upper'])) // @ts-expect-error -mapState(useStore, ['a']).nested +mapState(useOptionsStore, ['a']).nested // @ts-expect-error -mapState(useStore, ['a', 'upper']).nested +mapState(useOptionsStore, ['a', 'upper']).nested expectType<{ newA: () => 'on' | 'off' newUpper: () => string -}>(mapState(useStore, { newA: 'a', newUpper: 'upper' })) +}>(mapState(useOptionsStore, { newA: 'a', newUpper: 'upper' })) expectType<{ newA: () => 'on' | 'off' newUpper: () => string }>( - mapState(useStore, { + mapState(useOptionsStore, { newA: (store) => { expectType(store.upper) return store.a @@ -83,19 +97,24 @@ expectType<{ expectType<{ setToggle: (a: 'on' | 'off') => 'on' | 'off' toggleA: () => void -}>(mapActions(useStore, ['setToggle', 'toggleA'])) +}>(mapActions(useOptionsStore, ['setToggle', 'toggleA'])) expectType<{ newSetToggle: (a: 'on' | 'off') => 'on' | 'off' newToggleA: () => void -}>(mapActions(useStore, { newSetToggle: 'setToggle', newToggleA: 'toggleA' })) +}>( + mapActions(useOptionsStore, { + newSetToggle: 'setToggle', + newToggleA: 'toggleA', + }) +) expectType<{ a: { get: () => 'on' | 'off' set: (v: 'on' | 'off') => any } -}>(mapWritableState(useStore, ['a'])) +}>(mapWritableState(useOptionsStore, ['a'])) // @ts-expect-error: only defined in array mapWritableState(useStore, ['a']).b @@ -104,9 +123,33 @@ expectType<{ get: () => 'on' | 'off' set: (v: 'on' | 'off') => any } -}>(mapWritableState(useStore, { newA: 'a' })) +}>(mapWritableState(useOptionsStore, { newA: 'a' })) // @ts-expect-error: cannot use a getter mapWritableState(useStore, ['upper']) // @ts-expect-error: cannot use a getter mapWritableState(useStore, { up: 'upper' }) + +const setupStoreWithState = mapState(useSetupStore, ['a']) + +// store with no getters +expectType< + TypeEqual< + { + a: () => 'on' | 'off' + }, + typeof setupStoreWithState + > +>(true) + +const setupStoreWithGetters = mapState(useSetupStore, ['a', 'upper']) + +expectType< + TypeEqual< + { + a: () => 'on' | 'off' + upper: () => string + }, + typeof setupStoreWithGetters + > +>(true)