如何在TypeScript中强制对any类型对象使用可选链?
强制TypeScript对any类型对象使用可选链访问属性
要实现你想要的效果——直接访问any类型对象的属性时抛出检查错误,仅允许用可选链?.访问——可以通过以下两种方案实现:
方案一:自定义ESLint规则(精准约束)
TypeScript本身没有内置配置直接实现该需求,但可以通过ESLint结合@typescript-eslint工具链编写自定义规则来达成。
步骤说明:
- 先安装必要依赖:
npm install eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser @typescript-eslint/utils --save-dev
- 在项目根目录创建自定义规则文件,比如
./eslint-rules/require-optional-chain-for-any.js,内容如下:
const { ESLintUtils } = require('@typescript-eslint/utils'); const createRule = ESLintUtils.RuleCreator(() => ''); module.exports = createRule({ create(context) { const parserServices = ESLintUtils.getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); return { MemberExpression(node) { // 跳过已使用可选链的情况 if (node.optional) return; // 获取访问对象的TypeScript类型 const targetNode = parserServices.esTreeNodeToTSNode(node.object); const targetType = typeChecker.getTypeAtLocation(targetNode); // 若对象类型为any,则抛出错误 if (targetType.flags & typeChecker.TypeFlags.Any) { context.report({ node, message: '对any类型对象访问属性必须使用可选链(?.)', }); } }, }; }, name: 'require-optional-chain-for-any', meta: { type: 'problem', docs: { description: '强制对any类型对象的属性访问使用可选链', recommended: 'error', }, fixable: 'code', schema: [], }, defaultOptions: [], });
- 修改ESLint配置文件(如
.eslintrc.js),引入自定义规则:
module.exports = { parser: '@typescript-eslint/parser', parserOptions: { project: './tsconfig.json', // 需指向你的tsconfig文件 tsconfigRootDir: __dirname, }, plugins: ['@typescript-eslint', 'custom'], pluginPaths: ['./eslint-rules'], // 自定义规则所在目录 rules: { 'custom/require-optional-chain-for-any': 'error', }, };
配置完成后,直接访问any类型对象的属性(如e.code)会触发ESLint错误,而使用可选链e?.code则不会。
方案二:避免使用any类型(根源解决)
比强制约束更安全的方式是尽量不用any类型,改用更严格的类型定义:
1. 为错误定义具体类型
// 定义包含code属性的错误类型 interface ErrorWithCode extends Error { code?: string; } try { // ...业务代码 } catch(e) { const err = e as ErrorWithCode; const code = err?.code; // 开启strictNullChecks时,会提示code可能为undefined,自然会倾向于用可选链 }
2. 使用unknown类型代替any
unknown是TypeScript的安全替代类型,会强制你先做类型检查再访问属性:
try { // ...业务代码 } catch(e: unknown) { // 方式一:先缩小类型范围 if (typeof e === 'object' && e !== null && 'code' in e) { const code = (e as { code: string }).code; } // 方式二:直接用可选链(TypeScript 4.4+支持) const code = (e as { code?: string })?.code; }
内容的提问来源于stack exchange,提问作者GorvGoyl
相关产品推荐
相关产品推荐

