Skip to content

noBannedTypes

¥Summary

¥How to configure

biome.json
{
"linter": {
"rules": {
"complexity": {
"noBannedTypes": "error"
}
}
}
}

¥Description

禁止原始类型别名和误导性类型。

¥Disallow primitive type aliases and misleading types.

此规则旨在防止使用可能出现意外行为的潜在 “misleading” 类型和类型别名。

¥This rule aims to prevent usage of potentially “misleading” types and type aliases which may behave unexpectedly.

禁止使用 BooleanNumber 等 “装箱对象” 类型

Section titled “禁止使用 Boolean 和 Number 等 “装箱对象” 类型”

¥Disallow “boxed object” types like Boolean and Number

JavaScript 的 8 种数据类型在 TypeScript 中用小写字母 undefinednullbooleannumberstringbigintsymbolobject 来描述。

¥JavaScript’s 8 data types are described in TypeScript by the lowercase types undefined, null, boolean, number, string, bigint, symbol, and object.

后 6 个也都有大写变体,它们表示具有与其原始对应项共享属性的接口。由于结构类型学的特性,这些大写类型既接受原始值,也接受非原始的 “装箱对象” 类型(例如 new Boolean(true)),尽管两者在许多情况下(例如相等性和真值)的行为有所不同。

¥The latter 6 also have uppercase variants, which instead represent interfaces with the shared properties of their primitive counterparts. Due to the nature of structural typing, these uppercase types accept both primitive values and non-primitive “boxed object”s like new Boolean(true), despite the two behaving differently in many circumstances like equality and truthiness.

因此,最佳实践是避免使用 “装箱类型” 类型,而应使用其对应的小写原始类型。

¥It is thus considered best practice to avoid these “boxed types” in favor of their lowercase primitive counterparts.

¥Disallow the unsafe Function type

TypeScript 内置的 Function 类型能够接受任何形式的回调函数,其行为与直接调用 (...rest: any[]) => any(使用不安全的 any 类型)时的行为相同。它也接受恰好拥有 Function 类所有属性的类或普通对象,这同样可能造成混淆。

¥TypeScript’s built-in Function type is capable of accepting callbacks of any shape or form, behaving equivalent to (...rest: any[]) => any (which uses the unsafe any type) when called directly. It also accepts classes or plain objects that happen to possess all properties of the Function class, which is likewise a potential source of confusion.

因此,几乎总是建议尽可能显式地指定函数参数和返回类型。 当需要通用的 “catch-all” 回调类型时,可以使用以下方法之一:

¥As such, it is almost always preferable to explicitly specify function parameters and return types where possible.
When a generic “catch-all” callback type is required, one of the following can be used instead:

  • () => void:不接受任何参数且其返回值会被忽略的函数。

    ¥() => void: A function that accepts no parameters and whose return value is ignored

  • (...args: never) => unknown:“顶层类型” 用于可赋值为任何函数类型但不能直接调用的函数

    ¥(...args: never) => unknown: A “top type” for functions that can be assigned any function type, but can’t be called directly

禁止使用容易误导的空对象类型 {}

Section titled “禁止使用容易误导的空对象类型 {}”

¥Disallow the misleading empty object type {}

在 TypeScript 中,类型 {} 并不表示空对象(许多 TypeScript 新手可能会这样认为)。它实际上接受任何非空值,包括非对象基本类型。以下 TypeScript 示例因此完全有效:

¥In TypeScript, the type {} doesn’t represent an empty object (as many new to the language may assume). It actually accepts any non-nullish value, including non-object primitives. The following TypeScript example is thus perfectly valid:

const n: {} = 0;
code-block.ts:1:10 lint/complexity/noBannedTypes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Don’t use ’{}’ as a type.

> 1 │ const n: {} = 0;
^^
2 │

{}’ accepts any non-nullable value, including non-object primitives like ‘123’ and ‘true’.
- If you want a type meaning “any arbitrary object”, use ‘object’ instead.
- If you want a type meaning “any value”, use ‘unknown’ instead.
- If you want a type meaning “an object without any properties”, use ’{ [k: string]: never }’ or ‘Record<string, never>’ instead.

If that’s really what you want, use an inline disable comment.

通常,开发者编写的 {} 实际上是指以下情况之一:

¥Often, developers writing {} actually mean one of the following:

  • object:表示任何对象值

    ¥object: Represents any object value

  • unknown:表示任何值,包括 nullundefined

    ¥unknown: Represents any value at all, including null and undefined

  • { [k: string]: never }Record<string, never>:表示不允许属性访问的对象类型

    ¥{ [k: string]: never } or Record<string, never>: Represent object types that disallow property access

为避免混淆,此规则禁止使用 {} 类型,但以下两种情况除外:

¥To avoid confusion, this rule forbids the use of the type {}, except in two situations:

  1. 在类型约束中将泛型限制为非可空类型:

    ¥In type constraints to restrict a generic type to non-nullable types:

function f<T extends {}>(x: T) {
assert(x != null);
}
  1. 在类型交集中将类型缩小为其不可空的等效类型:

    ¥In a type intersection to narrow a type to its non-nullable equivalent type:

type NonNullableMyType = MyType & {};

在最后一种情况下,你也可以使用 NonNullable 工具类型来实现相同的效果:

¥In this last case, you can also use the NonNullable utility type to the same effect:

type NonNullableMyType = NonNullable<MyType>;

¥Examples

¥Invalid

let foo: String = "bar";
code-block.ts:1:10 lint/complexity/noBannedTypes  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Don’t use ‘String’ as a type.

> 1 │ let foo: String = “bar”;
^^^^^^
2 │

Prefer using lowercase primitive types instead of uppercase “boxed object” types.
String’ accepts anything that implements the corresponding interface - both primitives and “primitive-like” objects.
It is considered best practice to use ‘string’ instead in nearly all circumstances.

If that’s really what you want, use an inline disable comment.

Safe fix: Use ‘string’ instead.

1 - let·foo:·String·=·bar;
1+ let·foo:·string·=·bar;
2 2

const bool = true as Boolean;
code-block.ts:1:22 lint/complexity/noBannedTypes  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Don’t use ‘Boolean’ as a type.

> 1 │ const bool = true as Boolean;
^^^^^^^
2 │

Prefer using lowercase primitive types instead of uppercase “boxed object” types.
Boolean’ accepts anything that implements the corresponding interface - both primitives and “primitive-like” objects.
It is considered best practice to use ‘boolean’ instead in nearly all circumstances.

If that’s really what you want, use an inline disable comment.

Safe fix: Use ‘boolean’ instead.

1 - const·bool·=·true·as·Boolean;
1+ const·bool·=·true·as·boolean;
2 2

let invalidTuple: [string, Number] = ["foo", 12];
code-block.ts:1:28 lint/complexity/noBannedTypes  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Don’t use ‘Number’ as a type.

> 1 │ let invalidTuple: [string, Number] = [“foo”, 12];
^^^^^^
2 │

Prefer using lowercase primitive types instead of uppercase “boxed object” types.
Number’ accepts anything that implements the corresponding interface - both primitives and “primitive-like” objects.
It is considered best practice to use ‘number’ instead in nearly all circumstances.

If that’s really what you want, use an inline disable comment.

Safe fix: Use ‘number’ instead.

1 - let·invalidTuple:·[string,·Number]·=·[foo,·12];
1+ let·invalidTuple:·[string,·number]·=·[foo,·12];
2 2

function badFunction(cb: Function) {
cb(12);
}
code-block.ts:1:26 lint/complexity/noBannedTypes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Don’t use ‘Function’ as a type.

> 1 │ function badFunction(cb: Function) {
^^^^^^^^
2 │ cb(12);
3 │ }

The ‘Function’ type is unsafe and accepts any arbitrary function or “function-like” value.
Explicitly defining the function’s shape helps prevent mismatching argument types and return values.
If a generic “catch-all” callback type is required, consider using a “top type” like ’(…args: never) => unknown’ instead.

If that’s really what you want, use an inline disable comment.

const notEmpty: {} = {prop: 12};
code-block.ts:1:17 lint/complexity/noBannedTypes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Don’t use ’{}’ as a type.

> 1 │ const notEmpty: {} = {prop: 12};
^^
2 │

{}’ accepts any non-nullable value, including non-object primitives like ‘123’ and ‘true’.
- If you want a type meaning “any arbitrary object”, use ‘object’ instead.
- If you want a type meaning “any value”, use ‘unknown’ instead.
- If you want a type meaning “an object without any properties”, use ’{ [k: string]: never }’ or ‘Record<string, never>’ instead.

If that’s really what you want, use an inline disable comment.

const alsoNotAnObj: Object = "foo";
code-block.ts:1:21 lint/complexity/noBannedTypes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Don’t use ‘Object’ as a type.

> 1 │ const alsoNotAnObj: Object = “foo”;
^^^^^^
2 │

Object’ accepts any non-nullable value, including non-object primitives like ‘123’ and ‘true’.
- If you want a type meaning “any arbitrary object”, use ‘object’ instead.
- If you want a type meaning “any value”, use ‘unknown’ instead.
- If you want a type meaning “an object without any properties”, use ’{ [k: string]: never }’ or ‘Record<string, never>’ instead.

If that’s really what you want, use an inline disable comment.

¥Valid

const foo: string = "bar";
let tuple: [boolean, string] = [false, "foo"];
function betterFunction(cb: (n: number) => string) {
return cb(12);
}
type wrapFn<T extends (...args: never) => unknown> = { func: T }
const goodObj: object = {foo: 12};
type emptyObj = Record<string, never>;

{} 的例外情况:

¥Exceptions for {}:

declare function foo<T extends {}>(x: T): void;
type notNull<T> = T & {};

¥Related links