You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决Vue3 Pinia仓库TypeScript类型错误及进阶类型约束问题

问题解决与代码优化指南

一、修复getNewId中的TypeScript错误

错误原因

  • ts(2769):reduce的初始值设为0(数字类型),但你期望返回Transaction类型,类型不兼容导致类型推断失败。
  • ts(2339):因为初始值是数字,TypeScript认为prev可能是数字,而数字没有id属性,因此报错。

修复代码

由于else分支已经判断了this.transactions.length !== 0,可以直接用数组第一个元素作为reduce的初始值,确保类型完全匹配:

getNewId(): number {
    let newId = 0;
    if (this.transactions.length === 0) {
        newId = 1;
    } else {
        const transactionWithHighestId: Transaction = this.transactions.reduce((prev, current) => {
            return prev.id > current.id ? prev : current;
        }, this.transactions[0]); 
        const highestId = transactionWithHighestId.id;
        newId = highestId + 1;
    }
    return newId;
}

二、其他潜在错误的TypeScript优化点

  • 显式标注State类型
    当前state里的transactions是隐式推断类型,建议显式定义State接口,让类型更清晰,避免推断错误:

    interface TestStoreState {
        transactions: Transaction[];
    }
    
    export const useTestStore = defineStore('storeTest', {
        state: (): TestStoreState => ({ 
            transactions:  [/* 初始数据 */]
        }),
        // ...其余代码
    })
    
  • 限制transactionType为固定枚举值
    把transactionType从string改成联合类型,避免拼写错误(比如把Income写成income):

    type TransactionType = 'Income' | 'Expense';
    type Transaction = {
        id: number;
        description: string;
        transactionType: TransactionType;
        amount: number;
    }
    
  • 优化deleteTransaction中的类型处理
    用更简洁的类型守卫明确transactionToBeDeleted的非空状态:

    deleteTransaction(idOfTransactionToBeDeleted: number) {
        const transactionToBeDeleted = this.transactions.find(e => e.id === idOfTransactionToBeDeleted);
        if (!transactionToBeDeleted) {
            toast.error(`The transaction with ID, ${idOfTransactionToBeDeleted}, does not exist.`, {timeout: false});
            return;
        }
        // ...其余代码
    }
    
  • localStorage数据的类型安全处理
    初始化state时从localStorage读取数据,添加类型断言和检查,避免any类型风险:

    state: (): TestStoreState => {
        const savedTransactions = localStorage.getItem('transactions');
        return {
            transactions: savedTransactions ? (JSON.parse(savedTransactions) as Transaction[]) : [/* 默认数据 */]
        };
    }
    

三、确保id为整数、amount为小数的方法

TypeScript的number同时包含整数和小数,需要编译时类型约束+运行时验证结合:

1. 编译时类型约束

用语义化类型别名区分,提升代码可读性:

type TransactionId = number; // 语义化表示整数ID
type Amount = number; // 语义化表示金额(小数)

type Transaction = {
    id: TransactionId;
    description: string;
    transactionType: TransactionType;
    amount: Amount;
}

2. 运行时验证

在addTransaction中添加校验,确保数据符合要求:

addTransaction(newTransaction: Transaction) {
    // 验证id是整数
    if (!Number.isInteger(newTransaction.id)) {
        toast.error("Transaction ID must be an integer.", {timeout: false});
        return;
    }
    // 验证amount是最多两位小数的正数(根据业务调整规则)
    if (!Number.isFinite(newTransaction.amount) || newTransaction.amount < 0 || (newTransaction.amount * 100) % 1 !== 0) {
        toast.error("Amount must be a positive number with up to two decimal places.", {timeout: false});
        return;
    }
    // ...其余代码
}

内容的提问来源于stack exchange,提问作者Henry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:45:08