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

TypeScript点击Add Task报o.error is not a function错误

TypeScript待办应用Uncaught TypeError: o.error is not a function报错排查

问题场景

TypeScript初学者开发简易待办清单应用,目标是创建待办对象存入数组,后续基于数组渲染待办项到DOM。点击Add Task按钮时触发报错,相关代码如下:

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ts-todo</title>
    <link rel="stylesheet" href="../src/index.css">
</head>
<body>
    <main>
        <input type="text" name="todo" id="input" value="" >
        <button id="add-btn">Add Task</button>
        <ul id="todo">
        </ul>
    </main>
    <script src="./bundle.js"></script>
</body>
</html>

TypeScript代码

import { uuid } from "uuidv4"

// const ul = document.querySelector("#todo")as HTMLUListElement
const button = document.querySelector('#add-btn') as HTMLButtonElement
const input = document.querySelector("#input") as HTMLInputElement

// 存储待办对象的数组
let todos: object[] = []

interface Todos {
    id: string;
    todo: string; 
    completed: boolean;
    readonly createdDate: Date;
    updatedDate?: Date;
} 
let storeObject = (todo: string)=>{
    const item: Todos = {
        id: uuid(),
        todo: todo,
        completed: false ,
        createdDate: new Date,
    }
    todos.push({item})
    console.log('todos',todos);
}

button.addEventListener("click",(e)=>{
    console.log('enters in listener')
    if(input.value == "") return 
    storeObject(input.value)    
    input.value = ""
})

Webpack配置

const path = require('path');
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")

module.exports = {
  entry: './src/index.ts',
  devtool: 'inline-source-map',
  watch:true,
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  plugins: [
    new NodePolyfillPlugin()
  ],
  resolve: {
    extensions: ['.tsx', '.ts', '.js'], 
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

报错根因

报错和待办业务逻辑无关,完全是第三方依赖兼容问题导致:

  • 项目使用的老旧版本uuidv4包对ES Module导入、浏览器环境的适配存在缺陷,配合NodePolyfillPlugin做Node API polyfill时,包内部的日志调用代码被webpack压缩混淆后,无法找到对应的console.error方法,最终抛出o.error is not a function的类型错误。
  • 现有业务代码还存在三个隐藏问题,后续渲染时会触发异常:
    • todos数组标注类型为object[],丢失了自定义Todos接口的类型校验能力
    • 存储待办时写了todos.push({item}),会把合法的待办对象额外包一层item属性,后续读取id、待办文本时会拿到undefined
    • new Date未加执行括号属于不规范写法,虽然不会直接报错,但在部分环境下会出现异常返回值

修复方案

  1. 替换存在兼容问题的依赖:卸载老旧的uuidv4包,换成官方维护、原生支持TS与浏览器环境的uuid库,执行以下命令:
npm uninstall uuidv4
npm install uuid
npm install -D @types/uuid
  1. 修改TypeScript代码,修正导入、类型定义、存储逻辑的问题:
// 替换原有uuidv4的导入
import { v4 as uuidv4 } from 'uuid';

// 提前获取后续渲染需要的列表节点
const button = document.querySelector('#add-btn') as HTMLButtonElement
const input = document.querySelector("#input") as HTMLInputElement
const ul = document.querySelector("#todo") as HTMLUListElement

// 数组类型使用自定义Todos接口,获得完整类型校验
let todos: Todos[] = []

interface Todos {
    id: string;
    todo: string; 
    completed: boolean;
    readonly createdDate: Date;
    updatedDate?: Date;
} 

let storeObject = (todo: string)=>{
    const item: Todos = {
        id: uuidv4(),
        todo: todo,
        completed: false,
        createdDate: new Date(), // 补全Date的执行括号
    }
    // 直接存储待办对象,去掉多余的对象包裹
    todos.push(item)
    console.log('todos', todos);
}

button.addEventListener("click", ()=>{
    if(input.value.trim() === "") return 
    storeObject(input.value.trim())    
    input.value = ""
})
  1. 如果项目没有使用其他Node核心模块API,可以移除webpack配置中的NodePolyfillPlugin,减少不必要的polyfill注入,降低兼容问题出现概率。
  2. 重新执行webpack打包,点击Add Task按钮即可正常生成待办对象存入数组,控制台不会再抛出原有类型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:12:22