TypeScript错误:Object is of type 'unknown'.ts(2571) 导致代码无法部署至Vercel的求助
我明白你遇到的麻烦了——代码能正常运行,但TypeScript的报错卡住了Vercel部署,而且你已经排除了Stripe的问题。其实这个错误和Stripe完全无关,是TypeScript的类型推断规则导致的,咱们一步步搞定它。
错误原因分析
在你的isSubscriptionInCart函数里,cartDetails参数被定义为any类型。当你用Object.entries(cartDetails)遍历购物车项时,TypeScript会把返回的数组元素类型推断为[string, unknown]。这意味着cartItem[1]的类型是unknown,而TypeScript出于类型安全的考虑,不允许直接访问unknown类型的属性(比如.recurring),所以就抛出了Object is of type 'unknown'的错误。
虽然JavaScript运行时不会因为这个报错,但Vercel部署时会严格检查TypeScript的编译错误,所以才导致部署失败。
解决方案
方案1:定义明确的类型(推荐)
给购物车相关的数据定义TypeScript类型,这是最规范的做法,既能解决错误,还能提升代码的可维护性和类型安全性。
首先添加类型定义:
// 单个购物车项的类型,根据你的业务需求调整属性 interface CartItem { sku: string; quantity: number; recurring?: boolean; // 可选属性,因为不是所有商品都是订阅型 } // 购物车详情的类型:key是商品sku,value是对应的CartItem type CartDetails = Record<string, CartItem>;
然后修改两个处理购物车的函数,把参数类型从any换成上面定义的CartDetails:
const validateCartItems = (cartDetails: CartDetails) => { // 可以给返回值指定明确类型,让代码更严谨 const validatedItems: Stripe.Checkout.SessionCreateParams.LineItem[] = []; for (const sku in cartDetails) { const product = cartDetails[sku]; const item = { price: product.sku, quantity: product.quantity, }; validatedItems.push(item); } return validatedItems; }; const isSubscriptionInCart = (cartDetails: CartDetails) => { let subscriptionFound = false; for (const cartItem of Object.entries(cartDetails)) { // 现在TypeScript明确知道cartItem[1]是CartItem类型,不会再报错 if (cartItem[1].recurring) { subscriptionFound = true; } } return subscriptionFound; };
额外优化:你还可以在POST请求的处理逻辑里,给req.body添加强类型检查,进一步提升类型安全:
const cartItems: CartDetails = req.body; // 可选:添加简单的验证逻辑,确保cartItems的结构符合预期
方案2:临时类型断言(快速修复)
如果暂时不想定义完整的类型,可以用类型断言告诉TypeScriptcartItem[1]的具体类型,快速绕过错误:
const isSubscriptionInCart = (cartDetails: any) => { let subscriptionFound = false; for (const cartItem of Object.entries(cartDetails)) { // 断言cartItem[1]为包含recurring可选属性的类型 if ((cartItem[1] as { recurring?: boolean }).recurring) { subscriptionFound = true; } } return subscriptionFound; };
不过这种方法只是绕过TypeScript的检查,没有类型安全保障,还是优先推荐方案1。
修改完之后,TypeScript的错误应该就消失了,也能正常部署到Vercel了。
内容的提问来源于stack exchange,提问作者Stackerme

