Skip to content

docs: [no-wrapper-object-types] clean up a bit of phrasing #9363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

26 changes: 17 additions & 9 deletions packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@ import TabItem from '@theme/TabItem';
>
> See **https://typescript-eslint.io/rules/no-wrapper-object-types** for documentation.

The JavaScript language has a set of language types, but some of them correspond to two TypeScript types, which look similar: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, `object`/`Object`.
The difference is that the lowercase variants are compiler intrinsics and specify the actual _runtime types_ (that is, the return value when you use the `typeof` operator), while the uppercase variants are _structural types_ defined in the library that can be satisfied by any user-defined object with the right properties, not just the real primitives.
JavaScript also has a "wrapper" class object for each of those primitives, such as [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) and [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number).
These wrapper objects are assignable to the uppercase types, but not to the lowercase types.

Using the primitives like `0` instead of object wrappers like `new Number(0)` is generally considered a JavaScript best practice.
JavaScript programs typically work with the real number primitives, rather than objects that "look like" numbers.
Primitives are simpler to conceptualize and work with `==` and `===` equality checks -- which their object equivalents do notDeepEqual.
As a result, using the lowercase type names like `number` instead of the uppercase names like `Number` helps make your code behave more reliably.
TypeScript defines several confusing pairs of types that look very similar to each other, but actually mean different things: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, `object`/`Object`.
In general, only the lowercase variant is appropriate to use.
Therefore, this rule enforces that you only use the lowercase variant.

JavaScript has [8 data types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures) at runtime, and these are described in TypeScript by the lowercase types `undefined`, `null`, `boolean`, `number`, `string`, `bigint`, `symbol`, and `object`.

As for the uppercase types, these are _structural types_ which describe JavaScript "wrapper" objects for each of the data types, such as [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) and [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number).
Additionally, due to the quirks of structural typing, the corresponding primitives are _also_ assignable to these uppercase types, since they have the same "shape".

It is a universal best practice to work directly with the built-in primitives, like `0`, rather than objects that "look like" the corresponding primitive, like `new Number(0)`.

- Primitives have the expected value semantics with `==` and `===` equality checks, whereas their object counterparts are compared by reference.
That is to say, `"str" === "str"` but `new String("str") !== new String("str")`.
- Primitives have well-known behavior around truthiness/falsiness which is common to rely on, whereas all objects are truthy, regardless of the wrapped value (e.g. `new Boolean(false)` is truthy).
- TypeScript only allows arithmetic operations (e.g. `x - y`) to be performed on numeric primitives, not objects.

As a result, using the lowercase type names like `number` in TypeScript types instead of the uppercase names like `Number` is a better practice that describes code more accurately.

Examples of code for this rule:

Expand Down
Loading