Lit 2.2.5升级至3.1.1时出现TypeError问题求助
问题
将Lit从2.2.5升级到3.1.1后,页面触发以下错误:
Uncaught TypeError: e.constructor.createProperty is not a function at property.js:6:682 at property.js:6:768 at Object.decorateElement (property.js:6:776) at Object.<anonymous> (property.js:6:776) at Array.forEach (<anonymous>) at Object.decorateClass (property.js:6:776) at _decorate (property.js:6:776) at simple-element.ts:5:27 at app.ts:7:122
项目相关配置与代码如下:
babel.config.json
{"plugins": [["@babel/plugin-proposal-decorators", {"version": "2023-05"}]]}
package.json
{"name": "scg-envoy-litelement","version": "1.0.0","description": "","types": "dist/types/index.d.ts","author": "Jonathan Pong","license": "ISC","dependencies": {"@webcomponents/webcomponentsjs": "^2.8.0","lit": "^3.1.1","smoothscroll-polyfill": "^0.4.4","whatwg-fetch": "^3.6.20"},"devDependencies": {"@babel/core": "^7.23.7","@babel/eslint-parser": "^7.23.3","@babel/eslint-plugin": "^7.23.5","@babel/plugin-proposal-class-properties": "^7.18.6","@babel/plugin-proposal-decorators": "^7.23.7","@babel/plugin-proposal-object-rest-spread": "^7.18.6","@babel/plugin-transform-arrow-functions": "^7.23.3","@babel/preset-env": "^7.23.8","@babel/preset-typescript": "^7.23.3","@babel/runtime-corejs3": "^7.23.8","@open-wc/eslint-config": "^12.0.3","@open-wc/rollup-plugin-html": "^1.2.5","@rollup/plugin-babel": "^6.0.4","@rollup/plugin-commonjs": "^25.0.7","@rollup/plugin-node-resolve": "^15.2.3","@rollup/plugin-terser": "^0.4.4","@rollup/plugin-typescript": "11.1.6","@typescript-eslint/eslint-plugin": "^6.18.1","@typescript-eslint/parser": "^6.18.1","concurrently": "^8.2.2","core-js": "^3.35.0","eslint": "^8.56.0","eslint-config-prettier": "^9.1.0","eslint-plugin-babel": "^5.3.1","eslint-plugin-html": "^7.1.0","eslint-plugin-import": "^2.29.1","eslint-plugin-lit": "^1.11.0","eslint-plugin-lit-a11y": "^4.1.1","eslint-plugin-no-only-tests": "^3.1.0","eslint-plugin-wc": "^2.0.4","http-server": "^14.1.1","picomatch": "^3.0.1","rimraf": "^5.0.5","rollup": "^4.9.4","tslib": "^2.6.2","typescript": "^5.3.3"},"scripts": {"inst": "npm install && npm run build:types && npm run build:js","clean": "rimraf ./out","format": "eslint --ext .ts,.html . --fix","lint": "eslint --ext .ts,.html .","type-check": "tsc --noEmit","type-check:watch": "npm run type-check -- --watch","build:types": "tsc --emitDeclarationOnly","build:js": "rollup -c","build": "npm run build:types && npm run build:js","rebuild": "npm run clean && npm run build","server": "concurrently --kill-others --names tsc,http-server \"http-server\"","depcheck": "depcheck"},"eslintConfig": {"extends": ["@open-wc/eslint-config","eslint-config-prettier"]},"prettier": {"singleQuote": true,"arrowParens": "avoid"}}
rollup.config.mjs
import babel from '@rollup/plugin-babel'; import commonjs from '@rollup/plugin-commonjs'; import resolve from '@rollup/plugin-node-resolve'; import terser from '@rollup/plugin-terser'; const extensions = ['.js', '.ts', '.html']; const prod = false; function output() { const output = { dir: 'dist', format: 'iife', sourcemap: true, }; prod && (output.plugins = [terser()]); return output; } export default { input: ['src/app.ts'], strictDeprecations: true, output: output(), plugins: [ resolve({ extensions, browser: true }), commonjs({ sourcemap: true }), babel({ extensions, babelHelpers: 'inline', include: ['src/**/*'], presets: [ ['@babel/preset-typescript'], [ '@babel/preset-env', { targets: { browsers: '> 2%, ie >= 11' }, modules: false, spec: true, forceAllTransforms: true, useBuiltIns: 'usage', corejs: { version: 3, proposals: false }, }, ], ], plugins: [ ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }], ['@babel/proposal-class-properties'], ['@babel/proposal-object-rest-spread'], ['@babel/plugin-transform-arrow-functions'], ], }), ], };
tsconfig.json
{"compilerOptions": {"target": "es6","module": "es6","allowJs": true,"declaration": true,"declarationMap": true,"sourceMap": true,"declarationDir": "./dist/types","outDir": "./dist/tsc","rootDir": "./src","strict": true,"noUnusedLocals": false,"noUnusedParameters": false,"strictPropertyInitialization": false,"noImplicitReturns": true,"noImplicitAny": false,"noFallthroughCasesInSwitch": true,"moduleResolution": "node","allowSyntheticDefaultImports": true,"esModuleInterop": true,"experimentalDecorators": true,"useDefineForClassFields": false,"forceConsistentCasingInFileNames": true,"plugins": [{"name": "ts-lit-plugin","strict": true}]},"include": ["src/app.ts"],"exclude": ["node_modules","out"]}
app.ts
import '@webcomponents/webcomponentsjs' import 'core-js/modules/es.global-this' import 'whatwg-fetch' import { SimpleElement } from './simple-element' customElements.define("simple-element", SimpleElement); let simpleElement; window["simpleElement"] = () => simpleElement ? simpleElement : simpleElement = document.getElementById("simple-element");
simple-element.ts
import { html, LitElement } from 'lit'; import { property, customElement } from 'lit/decorators.js'; @customElement("simple-element") export class SimpleElement extends LitElement { private _runMode: String = ''; @property({ type: String }) get runMode(){ return this._runMode; } set runMode(rMode){ const oldValue = this._runMode; this._runMode = rMode; this.requestUpdate("disabled", oldValue); } render() { return html` <div> This is from a simple element with param <h2>${this.runMode}</h2> </div> `; } }
错误原因分析
- Lit 3.x装饰器兼容性问题:Lit 3.x完全采用TC39标准装饰器(2023-05版本),但项目中TypeScript仍启用
experimentalDecorators: true(旧版装饰器),两者冲突导致装饰器运行时无法调用createProperty方法。 - Babel与TypeScript配置不一致:Babel已配置使用标准装饰器,但TypeScript仍在使用实验性装饰器模式,编译后的代码无法适配Lit 3.x的装饰器逻辑。
- 类字段配置不兼容:TypeScript的
useDefineForClassFields: false与标准装饰器行为不匹配,Lit 3.x依赖标准类字段的处理逻辑。
解决建议
1. 统一装饰器为TC39标准模式
修改tsconfig.json,禁用实验性装饰器并启用标准配置:
{ "compilerOptions": { "experimentalDecorators": false, "useDefineForClassFields": true, // 其他原有配置保持不变 } }
2. 对齐Babel装饰器配置
更新rollup.config.mjs中的Babel插件配置,确保与TypeScript标准装饰器对齐:
plugins: [ ['@babel/plugin-proposal-decorators', { version: "2023-05", decoratorsBeforeExport: true }], ['@babel/plugin-proposal-class-properties', { "loose": false }], // 其他原有插件保持不变 ]
同时同步更新babel.config.json:
{"plugins": [["@babel/plugin-proposal-decorators", {"version": "2023-05", "decoratorsBeforeExport": true}], ["@babel/plugin-proposal-class-properties", {"loose": false}]]}
3. 修复业务代码错误
在simple-element.ts的setter中,requestUpdate的第一个参数应为属性名"runMode"而非"disabled",否则无法正确触发组件更新:
set runMode(rMode){ const oldValue = this._runMode; this._runMode = rMode; this.requestUpdate("runMode", oldValue); }
4. 清理依赖并重新构建
- 删除
node_modules和dist目录 - 执行
npm install重新安装依赖 - 执行
npm run build重新构建项目
内容的提问来源于stack exchange,提问作者Sreekumar Sekharan
相关产品推荐
相关产品推荐

