@qiun/eslint-plugin-ucharts
v3.0.0
Published
ESLint plugin for uCharts-v4 Safe TS Subset v3.0 — UTS/ArkTS/Swift/Kotlin cross-platform compliance rules
Maintainers
Readme
@qiun/eslint-plugin-ucharts
ESLint plugin for uCharts-v4 Safe TS Subset v3.0 — 11 条自定义规则,保障 TypeScript 代码可正确转译为 UTS / ArkTS / Swift / Kotlin
📋 规则列表(v3.0)
| 规则名 | 规则 ID | 默认级别 | 对应 Safe TS Subset 规则 | 说明 |
|--------|---------|---------|------------------------|------|
| no-destructuring | F-03~F-05 | error | 禁止解构赋值/声明/参数 | ArkTS 完全禁止解构 |
| no-object-spread | F-06 | error | 禁止对象展开 {...obj} | ArkTS 仅允许数组展开 |
| no-index-signature | F-07 | error | 禁止 Index Signature [key: T]: V | ArkTS 编译错误 |
| no-dynamic-property-access | F-08~F-09 | error | 禁止动态属性访问/添加 | 使用 Map 替代 |
| no-for-in | F-17 | error | 禁止 for...in 循环 | UTS/ArkTS 不支持 |
| no-with-statement | F-18 | error | 禁止 with 语句 | 四平台均不支持 |
| no-nested-function | F-21 | error | 禁止嵌套函数声明 | ArkTS 不支持 |
| require-null-over-undefined | M-01 | error | 强制用 null 替代 undefined | UTS/ArkTS 无 undefined |
| no-web-api-direct | M-07~M-12 | error | 禁止直接调用 Web API | console/rAF/perf/setTimeout |
| no-weakmap-proxy | M-04~M-05 | warn | 警告 WeakMap/Proxy | 各平台行为差异大 |
🎯 设计目标
以 UTS (uni-app x) 和 ArkTS (HarmonyOS NEXT) 为主要约束来源,因为这两个平台对 TypeScript 语法的限制最为严格。满足它们即自然满足 Swift/Kotlin。
最严格 ──────────────────────────────── 最宽松
ArkTS > UTS > Swift ≈ Kotlin > TypeScript🔧 安装与配置
安装
npm install @qiun/eslint-plugin-ucharts --save-dev配置(ESLint Flat Config — eslint.config.mjs)
import tsEslint from 'typescript-eslint';
import uchartsPlugin from '@qiun/eslint-plugin-ucharts';
export default [
{
files: ['**/*.{ts,js}'],
plugins: { '@qiun/ucharts': uchartsPlugin },
rules: {
// 全部启用(core/ 目录默认 error,其他目录可通过覆盖调整)
'@qiun/ucharts/no-destructuring': 'error',
'@qiun/ucharts/no-object-spread': 'error',
'@qiun/ucharts/no-index-signature': 'error',
'@qiun/ucharts/no-dynamic-property-access': ['error', {
allowStringLiteral: false,
allowKnownTypes: ['Array']
}],
'@qiun/ucharts/no-for-in': 'error',
'@qiun/ucharts/no-with-statement': 'error',
'@qiun/ucharts/no-nested-function': ['error', {
allowArrowFunctions: true,
allowMethods: true
}],
'@qiun/ucharts/require-null-over-undefined': 'error',
'@qiun/ucharts/no-web-api-direct': ['error', {
forbiddenApis: [
'console.log', 'console.warn', 'console.error', 'console.info',
'requestAnimationFrame', 'cancelAnimationFrame',
'performance.now', 'performance.measure',
'setTimeout', 'setInterval'
]
}],
'@qiun/ucharts/no-weakmap-proxy': 'warn'
}
}
];分层豁免示例
// merge.ts 工具函数内部需要动态属性访问和 Index Signature
{ files: ['core/util/merge.ts'], rules: {
'@qiun/ucharts/no-dynamic-property-access': 'off',
'@qiun/ucharts/no-index-signature': 'off'
}}
// platform/ 抽象层需要检测 Web API 和使用 undefined
{ files: ['core/platform/**/*.ts'], rules: {
'@qiun/ucharts/no-web-api-direct': 'off',
'@qiun/ucharts/require-null-over-undefined': 'off',
'@qiun/ucharts/no-dynamic-property-access': 'off'
}}📖 规则详解
no-destructuring
禁止所有形式的解构赋值:
// ❌ 错误
const { a, b } = obj;
function foo({ x, y }) {}
const fn = ({ name }) => name;
// ✅ 正确
const a = obj.a;
const b = obj.b;
function foo(options) { const x = options.x; const y = options.y; }
const fn = (options) => options.name;no-object-spread
禁止对象展开运算符(数组展开允许):
// ❌ 错误
const merged = { ...obj1, ...obj2 };
// ✅ 正确
const merged = merge(obj1, obj2);
const arr = [...arr1, ...arr2]; // 数组展开允许no-index-signature
禁止接口中的索引签名:
// ❌ 错误
interface Dict { [key: string]: number; }
// ✅ 正确
const dict = new Map<string, number>();
interface Dict { foo: number; bar: string; } // 显式字段no-dynamic-property-access
禁止使用变量作为属性键的访问方式:
// ❌ 错误
obj[variableKey];
obj[dynamicKey] = value;
// ✅ 正确
map.get(variableKey);
map.set(dynamicKey, value);
arr[index]; // Array 类型允许选项:
allowStringLiteral: 是否允许字符串字面量(默认 false)allowKnownTypes: 允许动态访问的类型列表(默认['Array'])
no-for-in
禁止 for...in 循环:
// ❌ 错误
for (const key in obj) { }
// ✅ 正确
for (const key of Object.keys(obj)) { }no-with-statement
禁止 with 语句:
// ❌ 错误
with (obj) { console.log(name); }
// ✅ 正确
const name = obj.name;
console.log(name);no-nested-function
禁止函数内部的嵌套函数声明(箭头函数和方法除外):
// ❌ 错误
function outer() {
function inner() {} // 嵌套函数声明
}
// ✅ 正确
function outer() {
const inner = () => {}; // 箭头函数允许
}
class Foo {
method() {
const helper = () => {}; // 方法内箭头函数允许
}
}选项:
allowArrowFunctions: 允许箭头函数(默认 true)allowMethods: 允许类方法内的定义(默认 true)
require-null-over-undefined
强制使用 null 而非 undefined:
// ❌ 错误
let x; // 隐式 undefined
let y = undefined;
if (x === undefined) { }
return undefined;
// ✅ 正确
let x = null;
let y = null;
if (x == null) { } // 同时检查 null/undefined
return null;no-web-api-direct
禁止直接调用浏览器/Web API,应使用平台抽象接口:
// ❌ 错误
console.log('msg');
requestAnimationFrame(cb);
setTimeout(fn, 1000);
// ✅ 正确
Logger.log('msg');
getAnimationScheduler().requestAnimationFrame(cb);
getAnimationScheduler().setTimeout(fn, 1000);选项:
forbiddenApis: 禁止的 API 列表(见上方配置示例)
no-weakmap-proxy
警告 WeakMap 和 Proxy 的使用:
// ⚠️ 警告
const wm = new WeakMap();
const p = new Proxy(target, handler);
// ✅ 推荐
const m = new Map();
// 使用显式适配器替代 Proxy