@foundbyte/eslint-plugin
v1.1.4-alpha.4
Published
ESLint plugin for enforcing code style rules including arrow function padding, Vue script lines limit, and TypeScript type comment requirements
Readme
@foundbyte/eslint-plugin
一个为 FoundByte 项目定制的 ESLint 插件,提供了一系列代码质量检查和最佳实践规则。
安装
npm install @foundbyte/eslint-plugin --save-dev
# 或
yarn add @foundbyte/eslint-plugin --dev
# 或
pnpm add @foundbyte/eslint-plugin --dev使用
在 ESLint 配置文件中添加插件:
// .eslintrc.js
module.exports = {
plugins: ['@foundbyte'],
rules: {
// 启用所有推荐的规则
'@foundbyte/arrow-function-padding': 'error',
'@foundbyte/no-initial-as-assertion': ['error', {
excludeVariableAssertions: true,
excludeTypePatterns: ['^const$', '^[A-Z]$', '^unknown$'],
excludeMethodReturns: ['parse', 'querySelector']
}],
'@foundbyte/hooks-arrow-function-only': 'error',
'@foundbyte/type-comment-requirement': ['error', {
minCommentsPerGroup: 1,
groupSize: 8,
includeTypes: true,
includeInterfaces: true,
}],
'@foundbyte/hooks-export-limit': ['error', { maxExports: 20 }],
'@foundbyte/vue-script-lines-limit': ['error', { maxLines: 300 }],
'@foundbyte/tag-attribute-restriction': ['error', {
restrictions: [
{
tag: 'image',
attributes: [
{ name: 'mode', disallowedValues: [''] },
]
}
]
}],
'@foundbyte/no-excessive-any': ['error', { maxAnyCount: 5 }],
},
}规则列表与配置示例
no-excessive-any
限制 any 类型的使用次数,包括:
- 显式
any类型 - 隐式
any类型(没有类型注解且无法推导类型的变量) - 泛型类型中的
any(如Ref<any>,Promise<any>,any[]等)
配置示例:
// 基本用法 - 限制 any 类型最多使用 5 次
'@foundbyte/no-excessive-any': ['error', { maxAnyCount: 5 }]
// 严格模式 - 禁止使用 any 类型
'@foundbyte/no-excessive-any': ['error', { maxAnyCount: 0 }]
// 宽松模式 - 允许最多 10 次 any 类型使用
'@foundbyte/no-excessive-any': ['error', { maxAnyCount: 10 }]检测范围:
- 显式
any类型:const a: any = 1 - 隐式
any类型:- 没有初始值的变量声明:
const a - 没有参数的函数调用:
const a = ref()
- 没有初始值的变量声明:
- 泛型类型中的
any:Ref<any>,Promise<any>,Array<any>any[],string | any,T extends any- 类型别名和接口中的
any
智能类型推导: 以下情况不计入 any 使用:
- 有初始值的变量:
const a = 1,const b = ref(60) - 对象字面量:
const obj = { name: 'test' } - 数组字面量:
const arr = [1, 2, 3] - 函数表达式和箭头函数:
const fn = () => {} - 有参数的函数调用:
const a = useRegex(phoneNum, 'phone-number') - 属性访问:
const value = ref.value - 异步函数调用:
const res = await ssoMobileAuth(...)
示例:
// ✅ 正确 - 当 maxAnyCount 为 3 时
const a: any = 1
const b: any = 'hello'
const c = ref() // 隐式 any
// ❌ 错误 - 当 maxAnyCount 为 3 时,第 4 次 any 使用会报错
const a: any = 1
const b: any = 'hello'
const c = ref() // 隐式 any
const d: any = true // 错误:any 类型使用次数不能超过 3 次,当前使用了 4 次
// ✅ 正确 - 使用具体类型
const a: number = 1
const b: string = 'hello'
const c: number = 123
const d: boolean = true
// ✅ 正确 - 可以推导类型的情况不计入 any 使用
const time = ref(60) // 有数字字面量参数,可以推导类型
const messages = { noMore: 'text' } // 对象字面量,可以推导类型
const fn = () => {} // 函数表达式,可以推导类型
const res = await ssoMobileAuth({ nonce: nonce.value }) // 异步函数调用,可以推导类型
// ❌ 错误 - 无法推导类型的隐式 any
const a // 没有初始值
const b = ref() // 没有参数的函数调用
const c: Ref<any> = ref() // 显式 any 类型
// ❌ 错误 - 泛型类型中的 any
type MyType<T = any> = T
interface MyInterface {
value: any
ref: Ref<any>
array: any[]
union: string | any
generic: Promise<any>
}配置选项:
maxAnyCount(number, 默认 0): 允许的any类型最大使用次数- 设置为 0 表示完全禁止使用
any类型 - 设置为正整数表示允许的最大次数
- 设置为 0 表示完全禁止使用
注意:
- 该规则统计文件中所有
any类型的使用,包括显式和隐式 - 规则会智能识别可以类型推导的情况,避免过度检测
- 建议在 TypeScript 项目中设置合理的限制,鼓励使用具体类型
- 对于遗留代码迁移,可以设置较高的限制值,然后逐步减少
no-initial-as-assertion
禁止在初始变量定义时使用 as 类型断言,强制使用显式类型注解。
配置示例:
// 基本用法
'@foundbyte/no-initial-as-assertion': 'error'
// 高级配置 - 排除特定情况
'@foundbyte/no-initial-as-assertion': ['error', {
excludeVariableAssertions: true, // 排除对变量的 as 断言
excludeMethodReturns: ['map', 'parse'] // 排除特定方法返回类型的 as 断言
}]示例:
// ✅ 正确 - 使用显式类型注解
const a: Ref<string> = ref()
const b: ComputedRef<number> = computed(() => {})
const c = ref() // 没有类型断言
const d: Ref<{ a: string }> = ref({}) // 使用显式类型注解
// ❌ 错误 - 在变量声明时使用 as 类型断言
const a = ref() as Ref<string>
const b = computed(() => {}) as ComputedRef<number>
const c = reactive({}) as Reactive<object>
const d = ref({} as { a: string }) // 嵌套的类型断言也会被检测到
// ✅ 当 excludeVariableAssertions 为 true 时 - 变量断言被排除
interface ID { a?: string, b?: string }
const d: ID = {}
const e = d as { a?: string } // 不会报错
// ✅ 当 excludeMethodReturns 包含 'map' 时 - 数组方法返回类型断言被排除
const arr = [1, 2, 3]
const mapped = arr.map(x => x * 2) as number[] // 不会报错
// ✅ 当 excludeMethodReturns 包含 'parse' 时 - JSON.parse 返回类型断言被排除
const jsonString = '{"name": "test"}'
const parsed = JSON.parse(jsonString) as { name: string } // 不会报错配置选项:
excludeVariableAssertions(boolean, 默认 false): 是否排除对变量的 as 断言- 当为 true 时,类似
const a = variable as Type的情况不会被报错 - 适用于变量到变量的类型断言场景
- 当为 true 时,类似
excludeMethodReturns(array, 默认 []): 排除特定方法返回类型的 as 断言- 支持数组方法:
map,filter,reduce等 - 支持全局函数:
JSON.parse等 - 支持链式调用:
arr.map().filter() as Type
- 支持数组方法:
excludeTypePatterns(array, 默认 []): 排除匹配正则表达式模式的类型断言- 支持正则表达式字符串数组
- 用于排除特定的类型断言模式,如
as const - 示例:
['^const$', '^Readonly<.*>$']可以排除as const和as Readonly<...>
注意:
- 该规则检查变量声明时的所有类型断言,包括嵌套在函数调用参数中的类型断言
- 推荐使用显式类型注解,因为类型断言会绕过 TypeScript 的类型检查
- 对于函数调用返回值的类型断言,可以通过配置选项排除特定情况
arrow-function-padding
要求函数体之间必须空行。
配置示例:
'@foundbyte/arrow-function-padding': 'error' // 总是要求空行示例:
// ✅ 正确
const one = () => {}
const two = () => {}
// ❌ 错误
const one = () => {}
const two = () => {}hooks-arrow-function-only
要求 React/Vue Hooks 必须使用箭头函数。
示例:
// ✅ 正确
const useMyHook = () => {
const [state, setState] = useState()
return state
};
// ❌ 错误
function useMyHook() {
const [state, setState] = useState()
return state
}hooks-export-limit
限制 Hooks 文件内部成员的导出数量。
配置示例:
'@foundbyte/hooks-export-limit': ['error', { maxExports: 2 }] // 最大允许的导出数量示例:
// ✅ 正确 - 只有一个导出
export const useMyHook = () => {
const a = ''
return {
a
}
}
// ❌ 错误 - 多个导出
export const useMyHook = () => {
const a = ''
const b = ''
return {
a,
b
}
}type-comment-requirement
要求复杂类型定义必须有类型注释。
配置示例:
'@foundbyte/type-comment-requirement': ['error', {
/** 至少1个注释 */
minCommentsPerGroup: 1,
/** 每3个类型 */
groupSize: 3,
}]示例:
// ✅ 正确 - 有类型注释
interface user {
/** 姓名 */
name: 'John'
/** 年龄 */
age: 30
ddress: { city: 'NY', zip: '10001' }
}
// ❌ 错误 - 复杂对象没有类型注释
interface user { name: 'John', age: 30, address: { city: 'NY', zip: '10001' } }vue-script-lines-limit
限制 Vue 单文件组件中 <script> 标签的行数。
配置示例:
'@foundbyte/vue-script-lines-limit': ['error', { maxLines: 200 }] // 最大允许的行数示例:
<!-- ✅ 正确 - script 标签行数在限制内 -->
<script>
export default {
data() {
return { count: 0 }
},
methods: {
increment() {
this.count++
}
}
}
</script>
<!-- ❌ 错误 - script 标签行数超过限制 -->
<script>
// ... 超过 200 行代码 ...
</script>tag-attribute-restriction
限制特定标签使用某些属性或属性值。
配置示例:
'@foundbyte/tag-attribute-restriction': ['error', {
restrictions: [
{
tag: 'image', // 标签名称
attributes: [ // 属性限制列表
{
name: 'mode', // 属性名称
disallowedValues: [ // 禁止的值列表(可选)
'',
'scaleToFill'
]
},
{
name: 'lazy-load' // 完全禁止该属性
}
]
}
]
}]支持的语法:
- 静态属性:
<image mode="" /> - 动态属性:
<image :mode="'scaleToFill'" /> - 无值属性:
<image lazy-load /> - 连字符属性名:
lazy-load,data-*等 - JSX 属性
示例:
<!-- ✅ 正确 -->
<image src="test.jpg" mode="aspectFit" />
<!-- ❌ 错误 - 禁止使用空字符串的 mode 属性 -->
<image mode="" />
<!-- ❌ 错误 - 禁止使用 scaleToFill 值 -->
<image :mode="'scaleToFill'" />
<!-- ❌ 错误 - 完全禁止 lazy-load 属性 -->
<image lazy-load />错误消息:
标签 <image> 不允许使用属性 mode- 当属性被完全禁止时标签 <image> 的属性 mode 不允许使用值 ""- 当特定属性值被禁止时
