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

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>
    `;
  }
}
错误原因分析
  1. Lit 3.x装饰器兼容性问题:Lit 3.x完全采用TC39标准装饰器(2023-05版本),但项目中TypeScript仍启用experimentalDecorators: true(旧版装饰器),两者冲突导致装饰器运行时无法调用createProperty方法。
  2. Babel与TypeScript配置不一致:Babel已配置使用标准装饰器,但TypeScript仍在使用实验性装饰器模式,编译后的代码无法适配Lit 3.x的装饰器逻辑。
  3. 类字段配置不兼容: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:05:55