如何编写ESLint规则禁止TypeScript品牌类型Milliseconds执行除法?
解决TypeScript品牌类型禁止除法的ESLint规则方案
核心问题本质
ESLint原生AST不会保留TypeScript的类型注解信息,单纯依赖AST选择器无法判断变量的实际类型。要实现基于类型的除法禁用检查,必须结合TypeScript的类型检查器(TypeChecker)来获取变量的类型元数据,而非仅靠语法节点匹配。
具体实现方案
1. 编写自定义ESLint规则
放弃仅使用no-restricted-syntax的思路,创建自定义规则,借助@typescript-eslint/parser和@typescript-eslint/utils工具包访问TypeScript的类型系统。
2. 获取类型检查器实例
在规则的create函数中,通过context.parserServices.getTypeChecker()获取TypeChecker实例,用于查询标识符的类型信息。
3. 检测除法表达式
针对AST中的BinaryExpression节点(对应除法运算符/),检查左右操作数是否为Milliseconds品牌类型:
- 若操作数是标识符,用TypeChecker获取其绑定的类型,判断是否匹配
Milliseconds。 - 若操作数是类型断言(
AsExpression),解析断言后的目标类型进行判断。
示例规则代码
import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils'; const createRule = ESLintUtils.RuleCreator(() => ''); export default createRule({ create(context) { const typeChecker = context.parserServices.getTypeChecker(); function isMillisecondsType(node: any): boolean { const tsType = typeChecker.getTypeAtLocation(node); const typeSymbol = tsType.getSymbol(); if (!typeSymbol) return false; // 匹配Milliseconds品牌类型的名称与标识属性 return typeSymbol.name === 'Milliseconds' && tsType.getProperties().some(prop => prop.name === '__type'); } return { BinaryExpression(node) { if (node.operator !== '/') return; const leftIsTargetType = isMillisecondsType(node.left); const rightIsTargetType = isMillisecondsType(node.right); if (leftIsTargetType || rightIsTargetType) { context.report({ node, message: '禁止对Milliseconds类型使用除法运算符', }); } }, }; }, meta: { docs: { description: '禁止对Milliseconds品牌类型执行除法操作' }, messages: { forbidden: '禁止对Milliseconds类型使用除法运算符' }, schema: [], type: 'problem', }, name: 'no-milliseconds-division', defaultOptions: [], });
关键细节说明
- 类型判断逻辑:通过TypeChecker获取节点的类型符号,验证名称是否为
Milliseconds,同时检查是否存在__type属性确认是品牌类型。 - 场景覆盖:同时处理已声明为
Milliseconds的变量、直接类型断言后的数值两种场景,全面禁用除法操作。 - 依赖配置:确保ESLint配置中使用
@typescript-eslint/parser,并在parserOptions中指定project指向你的tsconfig.json,否则TypeChecker无法正常工作。
ESLint配置示例
在.eslintrc中添加以下配置:
{ "parser": "@typescript-eslint/parser", "parserOptions": { "project": "./tsconfig.json" }, "plugins": ["@typescript-eslint"], "rules": { "your-plugin-name/no-milliseconds-division": "error" } }
内容的提问来源于stack exchange,提问作者Remot H
相关产品推荐
相关产品推荐

