From 5f6a172afb4d8fc0f7b6fb6da507685d1b84c5a9 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sat, 15 Jun 2024 14:00:59 -0600 Subject: [PATCH 1/8] clean up a bit of phrasing in no-wrapper-object-types --- .../eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index 858802470cbb..e2c8df1ad04f 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -10,13 +10,12 @@ 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. +The difference is that the lowercase variants are compiler intrinsics and specify the actual _runtime types_ (that is, the type indicated when executing `typeof x` at runtime), while the uppercase variants are _structural types_ defined in the library that can be satisfied by any user-defined object with the right properties, including but not limited to 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. +It is widely considered a JavaScript best practice to work with the built-in primitives, like `0`, rather than objects that "look like" numbers, like `new Number(0)`. +Primitives are simpler to conceptualize, work with `==` and `===` equality checks -- which their object equivalents do notDeepEqual -- and have well-known behavior around truthiness/falsiness which is common to rely on. As a result, using the lowercase type names like `number` instead of the uppercase names like `Number` helps make your code behave more reliably. Examples of code for this rule: From 13d2fadac83aaea4f3181da87c3f1e36531eefc6 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sat, 15 Jun 2024 14:08:53 -0600 Subject: [PATCH 2/8] directly --- packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index e2c8df1ad04f..f459bf21edd2 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -14,7 +14,7 @@ The difference is that the lowercase variants are compiler intrinsics and specif 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. -It is widely considered a JavaScript best practice to work with the built-in primitives, like `0`, rather than objects that "look like" numbers, like `new Number(0)`. +It is widely considered a JavaScript best practice to work directly with the built-in primitives, like `0`, rather than objects that "look like" numbers, like `new Number(0)`. Primitives are simpler to conceptualize, work with `==` and `===` equality checks -- which their object equivalents do notDeepEqual -- and have well-known behavior around truthiness/falsiness which is common to rely on. As a result, using the lowercase type names like `number` instead of the uppercase names like `Number` helps make your code behave more reliably. From 2a564bb8b43fa7d01fa4bbaec49b8db42a77641e Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Thu, 20 Jun 2024 18:45:49 -0600 Subject: [PATCH 3/8] pr feedback --- .../eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index f459bf21edd2..0ee476a7c3c8 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -14,8 +14,12 @@ The difference is that the lowercase variants are compiler intrinsics and specif 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. -It is widely considered a JavaScript best practice to work directly with the built-in primitives, like `0`, rather than objects that "look like" numbers, like `new Number(0)`. -Primitives are simpler to conceptualize, work with `==` and `===` equality checks -- which their object equivalents do notDeepEqual -- and have well-known behavior around truthiness/falsiness which is common to rely on. +It is widely considered a JavaScript 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) +- TS 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` instead of the uppercase names like `Number` helps make your code behave more reliably. Examples of code for this rule: From ca4b4eea33952c1b1601fea1113ee7b9696cddc1 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Thu, 20 Jun 2024 18:47:37 -0600 Subject: [PATCH 4/8] touchup --- packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index 0ee476a7c3c8..cc48a4c8d2c3 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -17,7 +17,7 @@ These wrapper objects are assignable to the uppercase types, but not to the lowe It is widely considered a JavaScript 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) +- 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). - TS 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` instead of the uppercase names like `Number` helps make your code behave more reliably. From b7a491d08784fc7ce95ea95eb25fa2d4dca3e4d8 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sat, 22 Jun 2024 15:17:51 -0600 Subject: [PATCH 5/8] Update packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Josh Goldberg ✨ --- packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index cc48a4c8d2c3..f85009cb4a9d 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -18,7 +18,7 @@ It is widely considered a JavaScript best practice to work directly with the bui - 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). -- TS only allows arithmetic operations (e.g. `x - y`) to be performed on numeric primitives, not objects. +- 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` instead of the uppercase names like `Number` helps make your code behave more reliably. From 38212229a2daed36ac38b0870e0335ca24735e8c Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sat, 22 Jun 2024 15:28:03 -0600 Subject: [PATCH 6/8] josh goldberg's suggestions --- .../docs/rules/no-wrapper-object-types.mdx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index f85009cb4a9d..79b09a18d946 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -9,10 +9,12 @@ 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 type indicated when executing `typeof x` at runtime), while the uppercase variants are _structural types_ defined in the library that can be satisfied by any user-defined object with the right properties, including but not limited to 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. +The JavaScript language has a set of built-in ("intrinsic") types which look similar: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, and `object`/`Object`. +The lowercase variants are _primitives_ such as `boolean` (e.g. `false`). +The uppercase variants are "wrapper" class objects for each of those primitives, such as [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) (e.g. `new Boolean(false)`). + +In TypeScript, the lowercase variants are compiler intrinsics and specify the actual _runtime types_ (that is, the type indicated when executing `typeof x` at runtime). +The uppercase variants are _structural types_ defined in the library that can be satisfied by any user-defined object with the right properties, including but not limited to the real primitives. It is widely considered a JavaScript 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)`. @@ -20,7 +22,7 @@ It is widely considered a JavaScript best practice to work directly with the bui - 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` instead of the uppercase names like `Number` helps make your code behave more reliably. +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: From d6448dc12b3ace3007a1ebf54160e92421ae3e03 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Wed, 3 Jul 2024 01:44:16 -0600 Subject: [PATCH 7/8] change docs again --- .../docs/rules/no-wrapper-object-types.mdx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index 79b09a18d946..6715a4c96203 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -9,16 +9,19 @@ import TabItem from '@theme/TabItem'; > > See **https://typescript-eslint.io/rules/no-wrapper-object-types** for documentation. -The JavaScript language has a set of built-in ("intrinsic") types which look similar: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, and `object`/`Object`. -The lowercase variants are _primitives_ such as `boolean` (e.g. `false`). -The uppercase variants are "wrapper" class objects for each of those primitives, such as [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) (e.g. `new Boolean(false)`). +TypeScript defines several confusing pairs of types that look very similar to each other, but actually mean quite 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. -In TypeScript, the lowercase variants are compiler intrinsics and specify the actual _runtime types_ (that is, the type indicated when executing `typeof x` at runtime). -The uppercase variants are _structural types_ defined in the library that can be satisfied by any user-defined object with the right properties, including but not limited to the real primitives. +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`. -It is widely considered a JavaScript 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)`. +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". -- 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")`. +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. From 6ff7c3e33fef5440a7af00c08ededc1fcebbd529 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger Date: Sun, 7 Jul 2024 23:53:52 -0600 Subject: [PATCH 8/8] Update packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Josh Goldberg ✨ --- packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx index 6715a4c96203..2d6a93371943 100644 --- a/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx +++ b/packages/eslint-plugin/docs/rules/no-wrapper-object-types.mdx @@ -9,7 +9,7 @@ import TabItem from '@theme/TabItem'; > > See **https://typescript-eslint.io/rules/no-wrapper-object-types** for documentation. -TypeScript defines several confusing pairs of types that look very similar to each other, but actually mean quite different things: `boolean`/`Boolean`, `number`/`Number`, `string`/`String`, `bigint`/`BigInt`, `symbol`/`Symbol`, `object`/`Object`. +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.