- 开发工具
- CLI
- Lint
- 格式化
- 静态分析
- 代码质量
- 构建工具
【免费下载链接】tools
Unified developer tools for JavaScript, TypeScript, and the web
noBannedTypes是 Rome(当前仓库gh_mirrors/to/tools,即 "Unified developer tools for JavaScript, TypeScript, and the web")在 TypeScript 语义分析中提供的一条 lint 规则,自 v10.0.0 起进入 nursery(试验)阶段。它用于禁止三类容易引入类型事故的写法:原始类型(primitive type)的大写别名(如String、Boolean)、过度宽泛的Function类型,以及含义与直觉相悖的非空类型{}。读完本文,你将掌握该规则的三条核心约束、两条内置例外、安全修复(Safe fix)的实际行为,以及如何通过rome.json和 CLI 参数启用、关闭或调整这条规则。
规则概述:一条规则,三类约束
规则文档(website/src/pages/lint/rules/noBannedTypes.md)将其能力概括为一句话:Disallow primitive type aliases and misleading types(禁止原始类型别名和具有误导性的类型)。具体拆解为以下三部分:
- 强制原始类型命名一致:原始类型存在别名,例如
Number是number的别名。规则推荐统一使用小写原始类型名。 - 禁止
Function类型:Function是宽松类型(loosely typed),被视为危险或有害的用法。它等价于使用了不安全any的(...rest: any[]) => any。 - 禁止具有误导性的非空类型
{}:在 TypeScript 中{}并不表示"空对象",而是表示"除null和undefined之外的任何值",例如下面的代码是完全合法的:
const n: {} = 0该规则从 typescript-eslint 的 ban-types)。
规则在仓库中的定位
- 所属分组:
lint/nursery(试验性规则组),注册于 crates/rome_js_analyze/src/semantic_analyzers/nursery.rs,并在 crates/rome_diagnostics_categories/src/categories.rs 中登记了诊断分类。 - 推荐启用:规则声明中
recommended: true(见 no_banned_types.rs),即按推荐配置运行时默认开启。 - 实现方式:规则的查询类型为
Semantic<TsBannedType>,其中TsBannedType是TsReferenceType | TsObjectType的联合节点(见 no_banned_types.rs),说明它运行在语义分析阶段,会结合绑定信息(binding model)判断标识符是否为全局类型。
约束一:禁止原始类型大写别名
TypeScript 中的原始类型拥有对应的大写包装器对象类型:Number、Boolean、String、Symbol、BigInt、Object。这些大写形式作为类型注解使用时几乎总是错误的选择——它们描述的是包装器对象而非原始值,且与团队其他成员书写的小写形式不一致。
从源码看,规则通过BannedType::from_str维护了一份完整的"黑名单"(见 no_banned_types.rs):
fn from_str(s: &str) -> Option<Self> { Some(match s { "BigInt" => Self::BigInt, "Boolean" => Self::Boolean, "Function" => Self::Function, "Number" => Self::Number, "Object" => Self::Object, "String" => Self::String, "Symbol" => Self::Symbol, "{}" => Self::EmptyObject, _ => return None, }) }对于这些原始类型别名,诊断消息统一为 "Use lowercase primitives for consistency."(使用小写原始类型以保持一致),并附带一条Safe fix(安全修复),把大写标识符原地替换为小写关键字。修复由fix_with()实现:它把BigInt/Boolean/Number/String/Symbol映射到对应的语法关键字BIGINT_KW/BOOLEAN_KW/NUMBER_KW/STRING_KW/SYMBOL_KW,再通过rome_js_factory生成新的引用标识符节点(见 no_banned_types.rs)。注意Function、Object和{}因为无法机械地改写为某个关键字,不会提供安全修复。
无效示例(Invalid)
let foo: String = "bar";运行规则后,Rome 会报告如下诊断(完整快照见 crates/rome_js_analyze/tests/specs/nursery/noBannedTypes/invalid.ts.snap):
nursery/noBannedTypes.js:1:10 lint/nursery/noBannedTypes FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━ ✖ Don't use 'String' as a type. > 1 │ let foo: String = "bar"; │ ^^^^^^ ℹ Use lowercase primitives for consistency. ℹ Safe fix: Use 'string' instead 1 │ - let foo: String = "bar"; 1 │ + let foo: string = "bar";其他同类无效示例:
let bool = true as Boolean; // 建议改为 boolean let invalidTuple: [string, Boolean] = ["foo", false]; // 建议改为 boolean规则对as断言、元组、泛型参数、类继承、接口实现等所有类型位置一视同仁。测试用例(invalid.ts)覆盖了函数参数、Array<String>、联合类型String | Object、泛型默认值class Foo<T = String>等大量场景。
有效示例(Valid)
let foo: string = "bar"; let tuple: [boolean, string] = [false, "foo"];关键例外:允许用户自定义同名类型
规则不是简单地"见String就报"。在run中,规则先通过model.binding(reference_identifier).is_none()检查该标识符是否绑定了本地声明:只有当它未被绑定(即全局标识符)时才触发诊断(见 no_banned_types.rs)。因此,用户完全可以在局部作用域内合法地声明并使用自己的Number别名,例如 valid.ts 中的用例:
namespace X { // Allow user aliases type Number = number function f(): Number { return 0; } }这段代码不会触发noBannedTypes,因为这里的Number绑定到了用户自定义的类型别名,而非全局包装器类型。
约束二:禁止Function类型
Function类型在 TypeScript 中几乎不提供任何类型信息:它接受任意函数形态的值,等价于(...rest: any[]) => any,底层依赖不安全的any。用它标注变量,等于放弃了参数与返回值的所有静态检查,是常见 bug 的来源。
触发诊断时,规则给出的提示为:
✖ Don't use 'Function' as a type. ℹ Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.例如以下代码会被报告(见 invalid.ts):
let fn: Function = () => true;正确做法是显式声明函数形态,例如() => boolean、(x: number) => string,或使用函数接口。由于Function没有对应的安全关键字替换,规则对它是只报告、不自动修复。
约束三:禁止误导性的非空类型{}
这是最容易让人踩坑的一条。在 TypeScript 中:
{}表示"除null和undefined之外的任何值",不是空对象;- 因此
const n: {} = 0完全合法,但这几乎肯定不是写代码的人的本意。
规则对此的报告如下(对应 website/src/pages/lint/rules/noBannedTypes.md 中的示例):
✖ Don't use '{}' as a type. ℹ Prefer explicitly define the object shape. '{}' means "any non-nullable value".如果需要真正表示"空对象",文档推荐使用以下两种等价写法之一:
{ [k: string]: never } Record<string, never>两条内置例外
为避免误伤合理的泛型约束写法,规则对{}给出了两个例外(文档说明见 noBannedTypes.md,实现见 no_banned_types.rs):
- 泛型约束:用
T extends {}将泛型参数限制为非空类型时允许。源码中通过检查ts_object_type.parent::<TsTypeConstraintClause>().is_none()来放行约束子句中的{}:
function f<T extends {}>(x: T) { assert(x != null); }- 类型交叉(intersection):用
T & {}把某个类型收窄为其非空等价形式时允许。源码通过ts_object_type.parent::<TsIntersectionTypeElementList>().is_none()放行交叉类型成员列表中的{}:
type NonNullableMyType = MyType & {};这两个例外在 valid.ts 中都有对应测试:
type PhoneNumber = number | null | undefined; type NonNullablePhoneNumber = PhoneNumber & {}; function consumeNonNullableValue<T extends {}>(value: T) {}对于最后一种交叉类型的场景,如果只是想表达"非空",文档还建议直接用 TypeScript 自带的工具类型,语义更清晰:
type NonNullableMyType = NonNullable<MyType>;其余有效写法
以下写法都不会触发规则(测试见 valid.ts):
let f = Object(); // 作为构造函数调用而非类型注解 let g = Object.create(null); let h = String(false); // 作为函数调用 let b: undefined; let c: null; let a: []; type Props = { foo: string; } // 显式定义对象形状注意Object在作为函数或构造函数调用(如Object()、String(false))时不受影响,规则只拦截它作为类型注解出现的位置。
配置与使用方式
通过 rome.json 配置
noBannedTypes属于linter.rules.nursery分组,可在rome.json中按需开启/关闭或降级为警告:
{ "linter": { "rules": { "nursery": { "noBannedTypes": "off" } } } }取值为"on" | "off" | "warn"。由于该规则recommended: true,在推荐配置下默认启用;若希望关闭,可将取值设为"off"。
通过 CLI 参数配置
从配置生成代码(crates/rome_service/src/configuration/linter/rules.rs)可以看到,每条规则都对应一个命令行参数,noBannedTypes对应:
rome check --linter-rules-nursery-no-banned-types=on src/ rome check --linter-rules-nursery-no-banned-types=off src/ rome check --linter-rules-nursery-no-banned-types=warn src/参数同样接受on|off|warn三种取值。noBannedTypes的启用状态最终会通过is_enabled()汇入规则过滤集合,由分析框架统一调度(见 rules.rs)。
针对单条规则的禁用与配置
若只需临时禁用某一行或某个文件的该规则,可参考项目文档中关于禁用 lint 规则与规则选项的通用说明(linter 页面中的 Disable a lint rule 与 Rule options 章节):
- 行内禁用:使用
// rome-ignore lint/nursery/noBannedTypes: <reason>注释,Rome 会据此跳过该行诊断; - 规则选项:通过配置对象为规则提供细化参数。
源码阅读指引
想深入理解这条规则,建议按以下路径阅读仓库:
- 规则实现:crates/rome_js_analyze/src/semantic_analyzers/nursery/no_banned_types.rs —— 完整包含
declare_rule!宏声明、run(查询与匹配)、diagnostic(诊断消息)和action(安全修复)四个核心部分; - 注册与分组:crates/rome_js_analyze/src/semantic_analyzers/nursery.rs —— 规则模块的注册入口;
- 配置生成:crates/rome_service/src/configuration/linter/rules.rs ——
no-banned-types命令行参数与nursery.noBannedTypes配置字段的定义; - 测试用例:invalid.ts 与 valid.ts,及其快照 invalid.ts.snap / valid.ts.snap —— 覆盖了全部禁止场景与例外场景,是理解规则边界的直接素材。
小结
noBannedTypes通过三把"闸门"提升 TypeScript 代码的类型严谨性:强制大写原始类型别名回归小写(并提供安全修复)、拒绝宽泛的Function、纠正对{}的误解(同时为泛型约束与交叉类型保留例外)。结合 no_banned_types.rs 的实现与 invalid.ts / valid.ts 的测试,你可以准确预判它在自己代码库中的行为边界,并借助rome.json或 CLI 参数按团队规范灵活调整。
- 开发工具
- CLI
- Lint
- 格式化
- 静态分析
- 代码质量
- 构建工具
【免费下载链接】tools
Unified developer tools for JavaScript, TypeScript, and the web
相关推荐
fairseq 字节级子词神经机器翻译:基于 IWSLT17 法英任务的 BBPE 完整实践指南
fairseq 字节级子词神经机器翻译:基于 IWSLT17 法英任务的 BBPE 完整实践指南 导读 本文以 fairseq 官方示例 byte_level_
开发工具CLILint格式化静态分析代码质量构建工具Rome 的 useShorthandArrayType 规则:用 `T[]` 简写统一 TypeScript 数组类型写法
Rome 的 useShorthandArrayType 规则:用 T 简写统一 TypeScript 数组类型写法 本文以 Rome(当前仓库 gh_mirr
开发工具CLILint格式化静态分析代码质量构建工具Rome Lint 规则详解:noClassAssign —— 禁止重赋值类成员
Rome Lint 规则详解:noClassAssign —— 禁止重赋值类成员 本文以 website/src/pages/lint/rules/noClas
开发工具CLILint格式化静态分析代码质量构建工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考