I’m new to Typescript. I am revising an existing a Pinia store in a Vue 3 project to use Typescript rather than Javascript and have managed to get rid of all of my squiggly lines, partly through the use of a type called Transaction
that was coded right in the store. Since I used this type throughout my app, I’m trying to figure out how to put my Transaction
type in a file by itself and then import it where needed but nothing I’ve tried seems to work: I inevitably get Typescript error 2307 on the import.
Here’s my Pinia store:
<code>import { defineStore } from 'pinia'
import { getSystemLocaleName } from '@dnvgl/i18n';
import { useToast } from 'vue-toastification';
const toast = useToast();
import Transaction from './types/Transaction.ts';
export const useTestStore = defineStore('storeTest', {
{ "id": 9, "description": "Salary", "transactionType": "Income", "amount": 3000.00 },
{ "id": 27, "description": "Air Fare", "transactionType": "Expense", "amount": 700.00 },
{ "id": 6, "description": "Taxi", "transactionType": "Expense", "amount": 30.00 }
addTransaction(newTransaction: Transaction): void {
/* Add the new transaction to the array in this store. */
this.transactions.push(newTransaction)
toast.success("Successfully added the transaction.", {timeout: 1000})
/* Update the array in local storage to reflect the added transaction. */
localStorage.setItem('transactions', JSON.stringify(this.transactions));
deleteTransaction(idOfTransactionToBeDeleted: number): void {
/* Find the transaction which is to be deleted via its Id. */
const transactionToBeDeleted = this.transactions.find(e => e.id == idOfTransactionToBeDeleted);
/* The value of transactionToBeDeleted will be undefined if no transaction exists with the
specified key. This could happen if another process deleted the transaction just before
this user tried to do so. If that happens, notify the user. */
if (typeof transactionToBeDeleted == 'undefined') {
toast.error("The transaction with ID," + idOfTransactionToBeDeleted + ", does not exist.", {timeout: false});
/* Find the index of the transaction which is to be deleted. */
const index: number = this.transactions.indexOf(transactionToBeDeleted);
/* Delete the indicated transaction from the array. */
this.transactions.splice(index, 1)
toast.success("Successfully deleted the transaction with ID " + idOfTransactionToBeDeleted + ".", {timeout: 1000})
/* Update the array in local storage to reflect the deleted transaction. */
localStorage.setItem('transactions', JSON.stringify(this.transactions));
if (this.transactions.length === 0) {
/* Use reduce() to find the transaction with the highest value of Id in the transactions array. */
const transactionWithHighestId: Transaction = this.transactions.reduce((prev, current) => {
return (prev && prev.id > current.id) ? prev : current}); //returns transaction
const highestId = transactionWithHighestId.id; //get the Id of the transaction that has the highest Id
newId = highestId + 1; //add 1 to the highest existing Id to get the Id of the new transaction
return (this.getIncome - this.getExpense)
/* Use filter() to make a new array containing only Income transactions. */
const incomeTransactions: Transaction[] = this.transactions.filter(transaction => transaction.transactionType === 'Income')
/* Use reduce() to sum up the Income transactions. */
const totalIncome = incomeTransactions.reduce((accumulator, currentValue) => accumulator + currentValue.amount, 0)
/* Use filter() to make a new array containing only Expense transactions. */
const expenseTransactions: Transaction[] = this.transactions.filter(transaction => transaction.transactionType === 'Expense')
/* Use reduce() to sum up the Expense transactions. */
const totalExpense = expenseTransactions.reduce((accumulator, currentValue) => accumulator + currentValue.amount, 0)
<code>import { defineStore } from 'pinia'
import { getSystemLocaleName } from '@dnvgl/i18n';
import { useToast } from 'vue-toastification';
const toast = useToast();
import Transaction from './types/Transaction.ts';
export const useTestStore = defineStore('storeTest', {
state: () => ({
transactions: [
{ "id": 9, "description": "Salary", "transactionType": "Income", "amount": 3000.00 },
{ "id": 27, "description": "Air Fare", "transactionType": "Expense", "amount": 700.00 },
{ "id": 6, "description": "Taxi", "transactionType": "Expense", "amount": 30.00 }
]
}),
actions: {
addTransaction(newTransaction: Transaction): void {
/* Add the new transaction to the array in this store. */
this.transactions.push(newTransaction)
toast.success("Successfully added the transaction.", {timeout: 1000})
/* Update the array in local storage to reflect the added transaction. */
localStorage.setItem('transactions', JSON.stringify(this.transactions));
},
deleteTransaction(idOfTransactionToBeDeleted: number): void {
/* Find the transaction which is to be deleted via its Id. */
const transactionToBeDeleted = this.transactions.find(e => e.id == idOfTransactionToBeDeleted);
/* The value of transactionToBeDeleted will be undefined if no transaction exists with the
specified key. This could happen if another process deleted the transaction just before
this user tried to do so. If that happens, notify the user. */
if (typeof transactionToBeDeleted == 'undefined') {
toast.error("The transaction with ID," + idOfTransactionToBeDeleted + ", does not exist.", {timeout: false});
return;
}
/* Find the index of the transaction which is to be deleted. */
const index: number = this.transactions.indexOf(transactionToBeDeleted);
/* Delete the indicated transaction from the array. */
this.transactions.splice(index, 1)
toast.success("Successfully deleted the transaction with ID " + idOfTransactionToBeDeleted + ".", {timeout: 1000})
/* Update the array in local storage to reflect the deleted transaction. */
localStorage.setItem('transactions', JSON.stringify(this.transactions));
}
},
getters: {
getNewId(): number {
let newId = 0;
if (this.transactions.length === 0) {
newId = 1;
} else {
/* Use reduce() to find the transaction with the highest value of Id in the transactions array. */
const transactionWithHighestId: Transaction = this.transactions.reduce((prev, current) => {
return (prev && prev.id > current.id) ? prev : current}); //returns transaction
const highestId = transactionWithHighestId.id; //get the Id of the transaction that has the highest Id
newId = highestId + 1; //add 1 to the highest existing Id to get the Id of the new transaction
}
return newId;
},
getBalance(): number {
return (this.getIncome - this.getExpense)
},
getIncome(): number {
/* Use filter() to make a new array containing only Income transactions. */
const incomeTransactions: Transaction[] = this.transactions.filter(transaction => transaction.transactionType === 'Income')
/* Use reduce() to sum up the Income transactions. */
const totalIncome = incomeTransactions.reduce((accumulator, currentValue) => accumulator + currentValue.amount, 0)
return totalIncome
},
getExpense(): number {
/* Use filter() to make a new array containing only Expense transactions. */
const expenseTransactions: Transaction[] = this.transactions.filter(transaction => transaction.transactionType === 'Expense')
/* Use reduce() to sum up the Expense transactions. */
const totalExpense = expenseTransactions.reduce((accumulator, currentValue) => accumulator + currentValue.amount, 0)
return totalExpense
}
}
})
</code>
import { defineStore } from 'pinia'
import { getSystemLocaleName } from '@dnvgl/i18n';
import { useToast } from 'vue-toastification';
const toast = useToast();
import Transaction from './types/Transaction.ts';
export const useTestStore = defineStore('storeTest', {
state: () => ({
transactions: [
{ "id": 9, "description": "Salary", "transactionType": "Income", "amount": 3000.00 },
{ "id": 27, "description": "Air Fare", "transactionType": "Expense", "amount": 700.00 },
{ "id": 6, "description": "Taxi", "transactionType": "Expense", "amount": 30.00 }
]
}),
actions: {
addTransaction(newTransaction: Transaction): void {
/* Add the new transaction to the array in this store. */
this.transactions.push(newTransaction)
toast.success("Successfully added the transaction.", {timeout: 1000})
/* Update the array in local storage to reflect the added transaction. */
localStorage.setItem('transactions', JSON.stringify(this.transactions));
},
deleteTransaction(idOfTransactionToBeDeleted: number): void {
/* Find the transaction which is to be deleted via its Id. */
const transactionToBeDeleted = this.transactions.find(e => e.id == idOfTransactionToBeDeleted);
/* The value of transactionToBeDeleted will be undefined if no transaction exists with the
specified key. This could happen if another process deleted the transaction just before
this user tried to do so. If that happens, notify the user. */
if (typeof transactionToBeDeleted == 'undefined') {
toast.error("The transaction with ID," + idOfTransactionToBeDeleted + ", does not exist.", {timeout: false});
return;
}
/* Find the index of the transaction which is to be deleted. */
const index: number = this.transactions.indexOf(transactionToBeDeleted);
/* Delete the indicated transaction from the array. */
this.transactions.splice(index, 1)
toast.success("Successfully deleted the transaction with ID " + idOfTransactionToBeDeleted + ".", {timeout: 1000})
/* Update the array in local storage to reflect the deleted transaction. */
localStorage.setItem('transactions', JSON.stringify(this.transactions));
}
},
getters: {
getNewId(): number {
let newId = 0;
if (this.transactions.length === 0) {
newId = 1;
} else {
/* Use reduce() to find the transaction with the highest value of Id in the transactions array. */
const transactionWithHighestId: Transaction = this.transactions.reduce((prev, current) => {
return (prev && prev.id > current.id) ? prev : current}); //returns transaction
const highestId = transactionWithHighestId.id; //get the Id of the transaction that has the highest Id
newId = highestId + 1; //add 1 to the highest existing Id to get the Id of the new transaction
}
return newId;
},
getBalance(): number {
return (this.getIncome - this.getExpense)
},
getIncome(): number {
/* Use filter() to make a new array containing only Income transactions. */
const incomeTransactions: Transaction[] = this.transactions.filter(transaction => transaction.transactionType === 'Income')
/* Use reduce() to sum up the Income transactions. */
const totalIncome = incomeTransactions.reduce((accumulator, currentValue) => accumulator + currentValue.amount, 0)
return totalIncome
},
getExpense(): number {
/* Use filter() to make a new array containing only Expense transactions. */
const expenseTransactions: Transaction[] = this.transactions.filter(transaction => transaction.transactionType === 'Expense')
/* Use reduce() to sum up the Expense transactions. */
const totalExpense = expenseTransactions.reduce((accumulator, currentValue) => accumulator + currentValue.amount, 0)
return totalExpense
}
}
})
This is Transaction.ts:
<code>type Transaction = {
<code>type Transaction = {
id: number;
description: string;
transactionType: string;
amount: number;
}
</code>
type Transaction = {
id: number;
description: string;
transactionType: string;
amount: number;
}
Transaction.ts is in a folder called types which is immediately below my src folder. My Pinia store is in a folder called store which is also immediately below my src folder.
This is my tsconfig.json:
"useDefineForClassFields": true,
"moduleResolution": "Node",
"resolveJsonModule": true,
"lib": ["ESNext", "DOM"],
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }],
"exclude": ["node_modules"]
<code> {
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true,
"paths": {
"@/*": [
"src/*"
]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }],
"exclude": ["node_modules"]
}
</code>
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true,
"paths": {
"@/*": [
"src/*"
]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }],
"exclude": ["node_modules"]
}
This is my tsconfig.node.json:
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
"include": ["vite.config.ts"]
<code> {
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
</code>
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
How do I coax Vue/Pinia/Typescript to “see” my type?