Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(types): mapHelpers with getters types (#2571) #2576

Merged
merged 1 commit into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions packages/pinia/src/mapHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ComponentPublicInstance } from 'vue-demi'
import type { ComponentPublicInstance, ComputedRef } from 'vue-demi'
import type {
_GettersTree,
_Method,
Expand Down Expand Up @@ -128,7 +128,7 @@ export function mapStores<Stores extends any[]>(
*/
export type _MapStateReturn<
S extends StateTree,
G extends _GettersTree<S>,
G extends _GettersTree<S> | { [key: string]: ComputedRef },
Keys extends keyof S | keyof G = keyof S | keyof G,
> = {
// [key in keyof S | keyof G]: () => key extends keyof S
Expand All @@ -145,7 +145,7 @@ export type _MapStateReturn<
export type _MapStateObjectReturn<
Id extends string,
S extends StateTree,
G extends _GettersTree<S>,
G extends _GettersTree<S> | { [key: string]: ComputedRef },
A,
T extends Record<
string,
Expand Down Expand Up @@ -198,7 +198,7 @@ export type _MapStateObjectReturn<
export function mapState<
Id extends string,
S extends StateTree,
G extends _GettersTree<S>,
G extends _GettersTree<S> | { [key: string]: ComputedRef },
A,
KeyMapper extends Record<
string,
Expand Down Expand Up @@ -235,7 +235,7 @@ export function mapState<
export function mapState<
Id extends string,
S extends StateTree,
G extends _GettersTree<S>,
G extends _GettersTree<S> | { [key: string]: ComputedRef },
A,
Keys extends keyof S | keyof G,
>(
Expand All @@ -254,7 +254,7 @@ export function mapState<
export function mapState<
Id extends string,
S extends StateTree,
G extends _GettersTree<S>,
G extends _GettersTree<S> | { [key: string]: ComputedRef },
A,
>(
useStore: StoreDefinition<Id, S, G, A>,
Expand Down
4 changes: 4 additions & 0 deletions packages/pinia/test-dts/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export * from '../dist/pinia'
// export * from '../src'

export type TypeEqual<Target, Value> =
(<T>() => T extends Target ? 1 : 2) extends <T>() => T extends Value ? 1 : 2
? true
: false
export function describe(_name: string, _fn: () => void): void
export function expectType<T>(value: T): void
export function expectError<T>(value: T): void
Expand Down
67 changes: 55 additions & 12 deletions packages/pinia/test-dts/mapHelpers.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { computed, ref } from 'vue'
import {
defineStore,
expectType,
mapStores,
mapActions,
mapState,
mapWritableState,
TypeEqual,
} from './'

const useStore = defineStore({
const useOptionsStore = defineStore({
id: 'name',
state: () => ({ a: 'on' as 'on' | 'off', nested: { counter: 0 } }),
getters: {
Expand All @@ -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 }),
Expand All @@ -34,11 +48,11 @@ const useStoreDos = defineStore({
state: () => ({}),
})

type MainStore = ReturnType<typeof useStore>
type MainStore = ReturnType<typeof useOptionsStore>
type DosStore = ReturnType<typeof useStoreDos>
type CounterStore = ReturnType<typeof useCounter>

const computedStores = mapStores(useStore, useStoreDos, useCounter)
const computedStores = mapStores(useOptionsStore, useStoreDos, useCounter)

expectType<{
nameStore: () => MainStore
Expand All @@ -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<string>(store.upper)
return store.a
Expand All @@ -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

Expand All @@ -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)
Loading