Omitted import
statements
Pinia
store: inputData.ts
interface State {
userInputValues: [
string, string, string, string,
string, string, string, string,
string, string, string, string,
string, string, string, string,
]
}
export const useInputDataStore = defineStore("inputData", {
state: (): State => {
return {
userInputValues: [
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
]
}
}
})
I know there should be 16 strings in the array, so I defined an interface
I have a component here:
<script setup lang="ts">
const store = useInputDataStore();
const { userInputValues } = storeToRefs(store);
const props = defineProps<{
inputId: number
}>();
// userInputValues is a Ref<[string, string, string...]>
// But how do I achieve it where I each string is a ref
// or userInputValues as Ref<[Ref<string>, Ref<string>, Ref<string>...]
// So here, inputBoxModel is a string not a Ref<string>
const inputBoxModel = userInputValues.value[inputId]
</script>
<template>
<input v-model="inputBoxModel" />
</template>
What I'm trying to do
I want to have an array of 16 Ref<string>
But...
When I access the array, whats returned is a string
, not a Ref<string>
So how can I make it reactive?
I would define a fixed size array type as:
type FixedSizeArray<N extends number, T> = {
length: N
} & ReadonlyArray<T>
which would make the store look like:
interface State {
form: FixedSizeArray<16, string>
}
export const useFormStore = defineStore('form', {
state: (): State => ({
form: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
})
})
And then you can import form
in any component and use it like you would any other store state property.
Working example: https://codesandbox.io/p/sandbox/sixteen-form-fnmjwg
Note: in the example I thought TS was smart enough to figure out that
Array.from({ length: 16 }).map(() => '')
satisfies FixedSizeArray<16, string>
but it gives the following error 1:
Type 'string[]' is not assignable to type 'FixedSizeArray<16, string>'.
Type 'string[]' is not assignable to type '{ length: 16; }'.
Types of property 'length' are incompatible.
Type 'number' is not assignable to type '16'.ts(2322)
For now, the only options are:
a) a type assertion
form: <FixedSizeArray<16, string>>Array.from({ length: 16 }).map(() => '')
b) repetition:
form: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
c) moving the type assertion into a function
As for your issues with reactivity, the question isn't clear enough. See App.vue
for implementation details in the above example.
1 - I've asked it as a separate question