{% endif %}
diff --git a/src/_includes/layouts/post.html b/src/_includes/layouts/post.html
index c9a539479..ea5a4e308 100644
--- a/src/_includes/layouts/post.html
+++ b/src/_includes/layouts/post.html
@@ -45,7 +45,9 @@
title: all_authors[author].title,
handle: all_authors[author].username,
github: all_authors[author].github_username,
+ bluesky: all_authors[author].bluesky_url,
twitter: all_authors[author].twitter_username,
+ mastodon: all_authors[author].mastodon_url,
bio: all_authors[author].bio
}) }}
{% endfor %}
diff --git a/src/_includes/partials/author_bios/joshuakgoldberg.md b/src/_includes/partials/author_bios/joshuakgoldberg.md
new file mode 100644
index 000000000..1980e0cfc
--- /dev/null
+++ b/src/_includes/partials/author_bios/joshuakgoldberg.md
@@ -0,0 +1 @@
+I'm involved with projects in the TypeScript ecosystem such as typescript-eslint, and wrote *Learning TypeScript* (O'Reilly).
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
new file mode 100644
index 000000000..ff66c02e4
--- /dev/null
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -0,0 +1,248 @@
+---
+layout: post
+title: "Differences between linting and type checking"
+teaser: "Linters such as ESLint and type checkers such as TypeScript catch different areas of code defects — and are best used in conjunction with each other."
+authors:
+ - joshuakgoldberg
+categories:
+ - Storytime
+tags:
+ - Linting
+---
+
+Linters and type checkers are two kinds of tools that both analyze code and report on detected issues.
+They may seem similar at first.
+However, the two kinds of tools detect very different issues and are useful in different ways.
+
+## Definitions
+
+*"Static analysis"* is the term for tooling that checks code for issues without running it.
+There are three forms of static analysis commonly used in web development projects today:
+
+1. **Formatters**: only print your code quickly, without worrying about logic
+2. **Linters**: execute individually configurable checks known as "lint rules"
+3. **Type checkers**: collect all files into a full understanding of the project
+
+We'll focus in this blog post on *linters*, namely ESLint, and *type checkers*, namely [TypeScript](https://typescriptlang.org).
+ESLint and TypeScript are often used together to detect defects in code.
+
+## Differences in Purpose
+
+Type checkers make sure the *intent* behind values in code matches the *usage* of those values.
+They check that code is "type-safe": meaning values are used according to the ways their types describe as being allowed.
+
+Type checkers do not attempt to look for defects that are only likely, rather than certain.
+Nor do type checkers enforce subjective opinions that might change between projects.
+That means TypeScript does not attempt to enforce general best practices — only that values are used in type-safe ways.
+TypeScript won't detect likely mistakes that work within those types.
+
+Linters, on the other hand, primarily target *likely* defects and can also be used to enforce subjective opinions.
+ESLint and other linters catch issues that are technically type-safe but are potential sources of bugs.
+Many developers rely on linters to make sure their code follow framework and language best practices.
+
+For example, developers sometimes leave out the `break` or `return` at the end of a `switch` statement's `case`.
+Doing so is type-safe and permitted by JavaScript and TypeScript.
+In practice, this is almost always a mistake that allows the next `case` statement to run accidentally.
+ESLint's [`no-fallthrough`](https://eslint.org/docs/latest/rules/no-fallthrough) can catch that likely mistake:
+
+```ts
+function logFruit(value: "apple" | "banana" | "cherry") {
+ switch (value) {
+ case "apple":
+ console.log("🍏");
+ break;
+
+ case "banana":
+ console.log("🍌");
+
+ // eslint(no-fallthrough):
+ // Expected a 'break' statement before 'case'.
+
+ case "cherry":
+ console.log("🍒");
+ break;
+ }
+}
+
+// Logs:
+// 🍌
+// 🍒
+logFruit("banana");
+```
+
+Another way of looking at the differences between linters and type checkers is that type checkers enforce what you *can* do, whereas linters enforce what you *should* do.
+
+### Granular Extensibility
+
+Another difference between linters and type checkers is how flexibly their areas of responsibility can be configured.
+
+Type checkers are generally configured with a set list of compiler options on a project level.
+TypeScript's [`tsconfig.json` ("TSConfig") files](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) allow for compiler options that change type checking for all files in the project.
+Those compiler options are set by TypeScript and generally change large swathes of type checking behavior.
+
+Linters, on the other hand, run with a configurable set of lint rules.
+Each lint rule can be granularly configured.
+If you don't like a particular lint rule, you can always turn it off for a line, set of files, or your entire project.
+
+Linters can also can be augmented by **plugins** that add new lint rules.
+Plugin-specific lint rules extend the breadth of code checks that linter configurations can pick and choose from.
+
+For example, this ESLint configuration enables the recommended rules from [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y), a plugin that adds checks for accessibility in JSX libraries such as Solid.js and React:
+
+```js title="eslint.config.js"
+import js from "@eslint/js";
+import jsxA11y from "eslint-plugin-jsx-a11y"
+
+export default [
+ js.configs.recommended,
+ jsxA11y.flatConfigs.recommended,
+ // ...
+];
+```
+
+A project using the JSX accessibility rules would then be told if they render a native `` tag without descriptive text per [`jsx-a11y/alt-text`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/alt-text.md):
+
+```tsx
+const MyComponent = () => ;
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// eslint(jsx-a11y/alt-text):
+// img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.
+```
+
+By adding in rules from plugins, linter configurations can be tailored to the specific best practices and common issues to the frameworks a project is built with.
+
+### Areas of Overlap
+
+Linters and type checkers operate differently and specialize in different areas of code defects.
+Some code defects straddle the line between "best practices" and "type safety", and so can be caught by both linting and type checking.
+There are some core rules in that are superseded by TypeScript's type checking.
+
+To make the most of both tools, we recommend:
+
+* In your ESLint configuration file, use the [ESLint `js.configs.recommended` config](https://eslint.org/docs/latest/use/getting-started#configuration), at least the [`tseslint.configs.recommended` configuration from typescript-eslint](https://typescript-eslint.io/getting-started/typed-linting), and any community plugins relevant to your project's libraries and frameworks
+* In your TypeScript configuration file, enable [`strict` mode](https://www.typescriptlang.org/tsconfig/#strict)
+
+typescript-eslint's recommended preset configs disable core ESLint rules that are not helpful with TypeScript.
+The configs leave on any core ESLint rules that are useful alongside type checking.
+
+#### Unused Locals and Parameters
+
+The only TypeScript compiler options we recommend keeping off when using linting are those that enable checking for unused variables:
+
+* [`noUnusedLocals`](https://www.typescriptlang.org/tsconfig/#noUnusedLocals): which reports on unused declared local variables
+* [`noUnusedParameters`](https://www.typescriptlang.org/tsconfig/#noUnusedParameters): which reports on unused function parameters
+
+Those compiler options are useful when not using a linter.
+However, they aren't configurable the way lint rules are, and so can't be configured to higher or lower strictness levels per a project's preferences.
+The compiler options are hardcoded to always ignore any variable whose name begins with `_`.
+
+As an example, the following `registerCallback` function declares two parameters for its callbacks -`id` and `message`- but the developer using it only needed `message`.
+TypeScript's `noUnusedParameters` compiler option would not flag the unused parameter `_`:
+
+```ts
+type Callback = (id: string, message: string) => void;
+
+declare function registerCallback(callback: Callback): void;
+
+// We only want to log message, not id
+registerCallback((_, message) => console.log(message));
+```
+
+Unused variables in JavaScript can also be caught by ESLint's [`no-unused-vars`](https://eslint.org/docs/latest/rules/no-unused-vars) rule; when in TypeScript code, the [`@typescript-eslint/no-unused-vars`](https://typescript-eslint.io/rules/no-unused-vars) is preferred instead.
+The lint rules by default also ignore variables whose name begins with `_`.
+They additionally ignore parameters that come before any parameter that is itself used.
+
+Some projects prefer to never allow unused parameters regardless of name or position.
+That stricter preferences helps prevent API designs that lead developers to creating many unused parameters.
+
+A more strict ESLint configuration would be able to report on the `_` parameter:
+
+```ts
+/* eslint @typescript-eslint/no-unused-vars: ["error", { "args": "all", "argsIgnorePattern": "" }] */
+
+type Callback = (id: string, message: string) => void;
+
+declare function registerCallback(callback: Callback): void;
+
+// We only want to log message, not id
+registerCallback((_, message) => console.log(message));
+// ~
+// eslint(@typescript-eslint/no-unused-vars):
+// '_' is declared but never used.
+```
+
+That extra level of configurability provided by the `no-unused-vars` rules can allow them to act as more granularly configurable versions of their equivalent TypeScript compiler options.
+
+> đź’ˇ See [`no-unused-binary-expressions`: From code review nit to ecosystem improvements](/blog/2024/10/code-review-nit-to-ecosystem-improvements) for more areas of code checking with partial overlap between linting and type checking.
+
+## Is a Linter Still Useful With a Type Checker?
+
+**Yes.**
+
+If you are using TypeScript, it is still very useful to use ESLint.
+In fact, linters and type checkers are at their most powerful when used in conjunction with each other.
+
+### Linters, With Type Information
+
+Traditional lint rules run on a single file at a time and have no knowledge of other files in the project.
+They can't make decisions on files based on contents of other files.
+
+However, if your project is set up using TypeScript, you can opt into "type checked" lint rules: rules that can pull in type information.
+In doing so, type checked lint rules can make decisions based on other files.
+
+For example, [`@typescript-eslint/no-for-in-array`](https://typescript-eslint.io/rules/no-for-in-array) is able to detect `for...in` loops over values that are array types, even if the values come from other files.
+TypeScript would not report a type error for a `for...in` loop over an array because doing so is technically type-safe and might be what a developer intended.
+A linter, however, could be configured to notice that the developer probably made a mistake and meant to use a `for...of` loop instead:
+
+```ts
+// declare function getArrayOfNames(): string[];
+import { getArrayOfNames } from "./my-names";
+
+for (const name in getArrayOfNames()) {
+ // eslint(@typescript-eslint/no-for-in-array):
+ // For-in loops over arrays skips holes, returns indices as strings,
+ // and may visit the prototype chain or other enumerable properties.
+ // Use a more robust iteration method such as for-of or array.forEach instead.
+ console.log(name);
+}
+```
+
+Augmenting the linter with information from the type checker makes for a more powerful set of lint rules.
+See [Typed Linting: The Most Powerful TypeScript Linting Ever](https://typescript-eslint.io/blog/typed-linting) for more details on typed linting with typescript-eslint.
+
+### Type Checkers, With Linting
+
+TypeScript adds extra complexity to JavaScript.
+That complexity is often worth it, but any added complexity brings with it the potential for misuse.
+Linters are useful for stopping developers from making TypeScript-specific blunders in code.
+
+For example, TypeScript's `{}` ("empty object") type is often misused by developers new to TypeScript.
+It visually looks like it should mean any `object`, but actually means any non-`null`, non-`undefined` value --- including primitives such as `number`s and `string`s.
+[`@typescript-eslint/no-empty-object-type`](https://typescript-eslint.io/rules/no-empty-object-type) catches uses of the `{}` type that likely meant `object` or `unknown` instead:
+
+```ts
+export function logObjectEntries(value: {}) {
+ // ~~
+ // eslint(@typescript-eslint/no-empty-object-type):
+ // The `{}` ("empty object") type allows any non-nullish value, including literals like `0` and `""`.
+ // - If that's what you want, disable this lint rule with an inline comment or configure the 'allowObjectTypes' rule option.
+ // - If you want a type meaning "any object", you probably want `object` instead.
+ // - If you want a type meaning "any value", you probably want `unknown` instead.
+ console.log(Object.entries(value));
+}
+
+logObjectEntries(0); // No type error!
+```
+
+Enforcing language-specific best practices with a linter helps developers learn about and correctly use type checkers such as TypeScript.
+
+## Conclusion
+
+Linters such as ESLint and type checkers such as TypeScript are both valuable assets for developers.
+The two catch different areas of code defects and come with different philosophies around configurability and extensibility.
+
+* Type checkers check that code is "type-safe": enforcing what you *can* write
+* Linters check that code adheres to best practices and is consistent: enforcing what you *should* write
+
+Put together, the two tools help projects write code with fewer bugs and more consistency.
+We recommend that any project that uses TypeScript additionally uses ESLint.
diff --git a/src/content/pages/team.html b/src/content/pages/team.html
index a16c4c27c..335f6cda1 100644
--- a/src/content/pages/team.html
+++ b/src/content/pages/team.html
@@ -29,10 +29,10 @@
{{ site.team_page.tsc.title }}
{% set itemName = item.name %}
{% set itemHandle = item.username %}
-
{% set itemBio = item.bio | safe %}
{% set itemWebsite = item.website %}
{% set itemGitHub = item.github_username %}
+ {% set itemBluesky = item.bluesky_url %}
{% set itemTwitter = item.twitter_username %}
{% set itemMastodon = item.mastodon_url %}
@@ -44,6 +44,7 @@
{% set itemName = item.name %}
{% set itemHandle = item.username %}
+
{% set itemBio = item.bio | safe %}
{% set itemWebsite = item.website %}
{% set itemGitHub = item.github_username %}
- {% set itemBluesky = item.bluesky_url %}
{% set itemTwitter = item.twitter_username %}
{% set itemMastodon = item.mastodon_url %}
@@ -212,7 +208,6 @@
{{ site.team_page.support_team.title }}
handleURL: itemHandleURL,
bio: itemBio,
website: itemWebsite,
- bluesky: itemBluesky,
github: itemGitHub,
twitter: itemTwitter,
mastodon: itemMastodon
From 49076ee1aaac383319e36d9c3ef4158a2f3e9edc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?=
Date: Fri, 6 Dec 2024 09:06:21 -0500
Subject: [PATCH 03/12] Apply suggestions from code review
Co-authored-by: Nicholas C. Zakas
Co-authored-by: Amaresh S M
---
...ences-between-linting-and-type-checking.md | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index ff66c02e4..2e86f15aa 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -14,9 +14,9 @@ Linters and type checkers are two kinds of tools that both analyze code and repo
They may seem similar at first.
However, the two kinds of tools detect very different issues and are useful in different ways.
-## Definitions
+## What is static analysis?
-*"Static analysis"* is the term for tooling that checks code for issues without running it.
+*Static analysis* is the inspection of source code without executing it. This differs from *dynamic analysis*, in which source code is inspected while it is executed. As such, dynamic analysis brings with it the inherent danger of executing malicious code or creating side effects while static analysis is safe to execute regardless of the source code.
There are three forms of static analysis commonly used in web development projects today:
1. **Formatters**: only print your code quickly, without worrying about logic
@@ -26,19 +26,19 @@ There are three forms of static analysis commonly used in web development projec
We'll focus in this blog post on *linters*, namely ESLint, and *type checkers*, namely [TypeScript](https://typescriptlang.org).
ESLint and TypeScript are often used together to detect defects in code.
-## Differences in Purpose
+## Digging deeper into linting vs. type checking
Type checkers make sure the *intent* behind values in code matches the *usage* of those values.
-They check that code is "type-safe": meaning values are used according to the ways their types describe as being allowed.
+They check that code is "type-safe": values are used according to how their types are described as being allowed.
Type checkers do not attempt to look for defects that are only likely, rather than certain.
Nor do type checkers enforce subjective opinions that might change between projects.
That means TypeScript does not attempt to enforce general best practices — only that values are used in type-safe ways.
TypeScript won't detect likely mistakes that work within those types.
-Linters, on the other hand, primarily target *likely* defects and can also be used to enforce subjective opinions.
-ESLint and other linters catch issues that are technically type-safe but are potential sources of bugs.
-Many developers rely on linters to make sure their code follow framework and language best practices.
+Linters, on the other hand, primarily target likely defects and can also be used to enforce subjective opinions.
+ESLint and other linters catch issues that are may or may not be type-safe but are potential sources of bugs.
+Many developers rely on linters to make sure their code follows framework and language best practices.
For example, developers sometimes leave out the `break` or `return` at the end of a `switch` statement's `case`.
Doing so is type-safe and permitted by JavaScript and TypeScript.
@@ -84,7 +84,7 @@ Linters, on the other hand, run with a configurable set of lint rules.
Each lint rule can be granularly configured.
If you don't like a particular lint rule, you can always turn it off for a line, set of files, or your entire project.
-Linters can also can be augmented by **plugins** that add new lint rules.
+Linters can also be augmented by **plugins** that add new lint rules.
Plugin-specific lint rules extend the breadth of code checks that linter configurations can pick and choose from.
For example, this ESLint configuration enables the recommended rules from [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y), a plugin that adds checks for accessibility in JSX libraries such as Solid.js and React:
@@ -115,7 +115,7 @@ By adding in rules from plugins, linter configurations can be tailored to the sp
Linters and type checkers operate differently and specialize in different areas of code defects.
Some code defects straddle the line between "best practices" and "type safety", and so can be caught by both linting and type checking.
-There are some core rules in that are superseded by TypeScript's type checking.
+There are some core rules that are superseded by TypeScript's type checking.
To make the most of both tools, we recommend:
@@ -153,7 +153,7 @@ The lint rules by default also ignore variables whose name begins with `_`.
They additionally ignore parameters that come before any parameter that is itself used.
Some projects prefer to never allow unused parameters regardless of name or position.
-That stricter preferences helps prevent API designs that lead developers to creating many unused parameters.
+These stricter preferences help prevent API designs that lead developers to create many unused parameters.
A more strict ESLint configuration would be able to report on the `_` parameter:
@@ -185,7 +185,7 @@ In fact, linters and type checkers are at their most powerful when used in conju
### Linters, With Type Information
Traditional lint rules run on a single file at a time and have no knowledge of other files in the project.
-They can't make decisions on files based on contents of other files.
+They can't make decisions on files based on the contents of other files.
However, if your project is set up using TypeScript, you can opt into "type checked" lint rules: rules that can pull in type information.
In doing so, type checked lint rules can make decisions based on other files.
From ad13f710d7ba760157937656ae8d5d5f9e78797b Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Fri, 6 Dec 2024 09:44:30 -0500
Subject: [PATCH 04/12] Clean up per nzakas review
---
...ences-between-linting-and-type-checking.md | 39 +++++++++++++++----
1 file changed, 31 insertions(+), 8 deletions(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index 2e86f15aa..2378fe335 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -10,20 +10,29 @@ tags:
- Linting
---
+If you're a JavaScript developer today, you're probably using ESLint and/or TypeScript to assist development.
+Those two tools are common examples of their kind of tooling: ESLint is a common *linter*, whereas TypeScript is a common *type checker*.
+
Linters and type checkers are two kinds of tools that both analyze code and report on detected issues.
They may seem similar at first.
+They both fall under the category of *static analysis*.
However, the two kinds of tools detect very different issues and are useful in different ways.
## What is static analysis?
-*Static analysis* is the inspection of source code without executing it. This differs from *dynamic analysis*, in which source code is inspected while it is executed. As such, dynamic analysis brings with it the inherent danger of executing malicious code or creating side effects while static analysis is safe to execute regardless of the source code.
-There are three forms of static analysis commonly used in web development projects today:
+Static analysis is the inspection of source code without executing it.
+This differs from *dynamic analysis*, in which source code is inspected while it is executed.
+As such, dynamic analysis brings with it the inherent danger of executing malicious code or creating side effects while static analysis is safe to execute regardless of the source code.
-1. **Formatters**: only print your code quickly, without worrying about logic
-2. **Linters**: execute individually configurable checks known as "lint rules"
-3. **Type checkers**: collect all files into a full understanding of the project
+Static analysis can be immensely helpful for improving code readability, reliability, and overall quality.
+Many developers rely on static analysis to enforce consistent code formatting and style, to ensure code is well-documented, and to catch likely bugs.
+Because static analysis runs on source code, it can suggest improvements in editors, as code is written.
We'll focus in this blog post on *linters*, namely ESLint, and *type checkers*, namely [TypeScript](https://typescriptlang.org).
+
+* **ESLint**: executes individually configurable checks known as "lint rules"
+* **TypeScript**: collects all files into a full understanding of the project
+
ESLint and TypeScript are often used together to detect defects in code.
## Digging deeper into linting vs. type checking
@@ -31,7 +40,21 @@ ESLint and TypeScript are often used together to detect defects in code.
Type checkers make sure the *intent* behind values in code matches the *usage* of those values.
They check that code is "type-safe": values are used according to how their types are described as being allowed.
-Type checkers do not attempt to look for defects that are only likely, rather than certain.
+For example, TypeScript would report a type error on the following `logUppercase(9001)` call, because `logUppercase` is declared as receiving a `string` rather than a `number`:
+
+```ts
+function logUppercase(text: string) {
+ console.log(text.toUpperCase());
+}
+
+logUppercase(9001);
+```
+
+Compiled languages such as Java and Rust perform type checking as part of their compilation step.
+Because JavaScript is an interpreted language, TypeScript is run separately.
+
+Type checkers generally do not attempt to look for defects that are only likely to occur.
+Type checkers generally only look for defects that are certainly wrong.
Nor do type checkers enforce subjective opinions that might change between projects.
That means TypeScript does not attempt to enforce general best practices — only that values are used in type-safe ways.
TypeScript won't detect likely mistakes that work within those types.
@@ -74,9 +97,9 @@ Another way of looking at the differences between linters and type checkers is t
### Granular Extensibility
-Another difference between linters and type checkers is how flexibly their areas of responsibility can be configured.
+Another difference between ESLint and TypeScript is how flexibly their areas of responsibility can be configured.
-Type checkers are generally configured with a set list of compiler options on a project level.
+TypeScript is configured by a set list of compiler options on a project level.
TypeScript's [`tsconfig.json` ("TSConfig") files](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) allow for compiler options that change type checking for all files in the project.
Those compiler options are set by TypeScript and generally change large swathes of type checking behavior.
From 62ca3490183011bc821962ed3ea0e703d622c2bb Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Fri, 6 Dec 2024 09:45:57 -0500
Subject: [PATCH 05/12] Add ~~~~ for TS
---
.../2024-12-04-differences-between-linting-and-type-checking.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index 2378fe335..08f986ab0 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -48,6 +48,8 @@ function logUppercase(text: string) {
}
logUppercase(9001);
+// ~~~~
+// Argument of type 'number' is not assignable to parameter of type 'string'.
```
Compiled languages such as Java and Rust perform type checking as part of their compilation step.
From 822514ddbc6e5237650e29a983072cd148542029 Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Fri, 6 Dec 2024 10:09:23 -0500
Subject: [PATCH 06/12] Clarify focus as on ESLint and TypeScript
---
...ences-between-linting-and-type-checking.md | 46 ++++++++++---------
1 file changed, 25 insertions(+), 21 deletions(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index 08f986ab0..177e0c921 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -28,12 +28,14 @@ Static analysis can be immensely helpful for improving code readability, reliabi
Many developers rely on static analysis to enforce consistent code formatting and style, to ensure code is well-documented, and to catch likely bugs.
Because static analysis runs on source code, it can suggest improvements in editors, as code is written.
-We'll focus in this blog post on *linters*, namely ESLint, and *type checkers*, namely [TypeScript](https://typescriptlang.org).
+We'll focus in this blog post on ESLint and TypeScript:
* **ESLint**: executes individually configurable checks known as "lint rules"
* **TypeScript**: collects all files into a full understanding of the project
-ESLint and TypeScript are often used together to detect defects in code.
+ESLint and TypeScript use some of the same forms of analysis to detect defects in code.
+They both analyze how scopes and variables are created and used in code, and can catch issues such as referencing a variable that doesn't exist.
+We'll explore the different ways the two use information from analyzing your code.
## Digging deeper into linting vs. type checking
@@ -56,9 +58,10 @@ Compiled languages such as Java and Rust perform type checking as part of their
Because JavaScript is an interpreted language, TypeScript is run separately.
Type checkers generally do not attempt to look for defects that are only likely to occur.
-Type checkers generally only look for defects that are certainly wrong.
+They generally only look for uses of code that are certainly wrong.
+
Nor do type checkers enforce subjective opinions that might change between projects.
-That means TypeScript does not attempt to enforce general best practices — only that values are used in type-safe ways.
+TypeScript does not attempt to enforce general best practices — only that values are used in type-safe ways.
TypeScript won't detect likely mistakes that work within those types.
Linters, on the other hand, primarily target likely defects and can also be used to enforce subjective opinions.
@@ -95,24 +98,24 @@ function logFruit(value: "apple" | "banana" | "cherry") {
logFruit("banana");
```
-Another way of looking at the differences between linters and type checkers is that type checkers enforce what you *can* do, whereas linters enforce what you *should* do.
+Another way of looking at the differences between ESLint and TypeScript is that TypeScript enforces what you *can* do, whereas ESLint enforces what you *should* do.
### Granular Extensibility
Another difference between ESLint and TypeScript is how flexibly their areas of responsibility can be configured.
TypeScript is configured by a set list of compiler options on a project level.
-TypeScript's [`tsconfig.json` ("TSConfig") files](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) allow for compiler options that change type checking for all files in the project.
+Its [`tsconfig.json` ("TSConfig") files](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) allow for compiler options that change type checking for all files in the project.
Those compiler options are set by TypeScript and generally change large swathes of type checking behavior.
-Linters, on the other hand, run with a configurable set of lint rules.
+ESLint on the other hand, runs with a configurable set of lint rules.
Each lint rule can be granularly configured.
If you don't like a particular lint rule, you can always turn it off for a line, set of files, or your entire project.
-Linters can also be augmented by **plugins** that add new lint rules.
-Plugin-specific lint rules extend the breadth of code checks that linter configurations can pick and choose from.
+ESLint can also be augmented by **plugins** that add new lint rules.
+Plugin-specific lint rules extend the breadth of code checks that ESLint configurations can pick and choose from.
-For example, this ESLint configuration enables the recommended rules from [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y), a plugin that adds checks for accessibility in JSX libraries such as Solid.js and React:
+For example, this ESLint configuration enables the recommended rules from [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y), a plugin that adds checks for accessibility in projects using JSX libraries such as Solid.js and React:
```js title="eslint.config.js"
import js from "@eslint/js";
@@ -125,7 +128,8 @@ export default [
];
```
-A project using the JSX accessibility rules would then be told if they render a native `` tag without descriptive text per [`jsx-a11y/alt-text`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/alt-text.md):
+A project using the JSX accessibility rules would then be told if their code violates common accessibility guidelines.
+For example, rendering a native `` tag without descriptive text would receive a report from [`jsx-a11y/alt-text`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/alt-text.md):
```tsx
const MyComponent = () => ;
@@ -134,11 +138,11 @@ const MyComponent = () => ;
// img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.
```
-By adding in rules from plugins, linter configurations can be tailored to the specific best practices and common issues to the frameworks a project is built with.
+By adding in rules from plugins, ESLint configurations can be tailored to the specific best practices and common issues to the frameworks a project is built with.
### Areas of Overlap
-Linters and type checkers operate differently and specialize in different areas of code defects.
+ESLint and TypeScript operate differently and specialize in different areas of code defects.
Some code defects straddle the line between "best practices" and "type safety", and so can be caught by both linting and type checking.
There are some core rules that are superseded by TypeScript's type checking.
@@ -200,14 +204,14 @@ That extra level of configurability provided by the `no-unused-vars` rules can a
> đź’ˇ See [`no-unused-binary-expressions`: From code review nit to ecosystem improvements](/blog/2024/10/code-review-nit-to-ecosystem-improvements) for more areas of code checking with partial overlap between linting and type checking.
-## Is a Linter Still Useful With a Type Checker?
+## Is a ESLint Still Useful With TypeScript?
**Yes.**
If you are using TypeScript, it is still very useful to use ESLint.
-In fact, linters and type checkers are at their most powerful when used in conjunction with each other.
+In fact, ESLint and TypeScript are at their most powerful when used in conjunction with each other.
-### Linters, With Type Information
+### ESLint, With Type Information
Traditional lint rules run on a single file at a time and have no knowledge of other files in the project.
They can't make decisions on files based on the contents of other files.
@@ -232,10 +236,10 @@ for (const name in getArrayOfNames()) {
}
```
-Augmenting the linter with information from the type checker makes for a more powerful set of lint rules.
+Augmenting ESLint with information from TypeScript makes for a more powerful set of lint rules.
See [Typed Linting: The Most Powerful TypeScript Linting Ever](https://typescript-eslint.io/blog/typed-linting) for more details on typed linting with typescript-eslint.
-### Type Checkers, With Linting
+### TypeScript, With Linting
TypeScript adds extra complexity to JavaScript.
That complexity is often worth it, but any added complexity brings with it the potential for misuse.
@@ -259,15 +263,15 @@ export function logObjectEntries(value: {}) {
logObjectEntries(0); // No type error!
```
-Enforcing language-specific best practices with a linter helps developers learn about and correctly use type checkers such as TypeScript.
+Enforcing language-specific best practices with ESLint helps developers learn about and correctly use TypeScript.
## Conclusion
Linters such as ESLint and type checkers such as TypeScript are both valuable assets for developers.
The two catch different areas of code defects and come with different philosophies around configurability and extensibility.
-* Type checkers check that code is "type-safe": enforcing what you *can* write
-* Linters check that code adheres to best practices and is consistent: enforcing what you *should* write
+* TypeScripts checks that code is "type-safe": enforcing what you *can* write
+* ESLint checks that code adheres to best practices and is consistent: enforcing what you *should* write
Put together, the two tools help projects write code with fewer bugs and more consistency.
We recommend that any project that uses TypeScript additionally uses ESLint.
From 142fcaf17e2360505ec34a0761eeb0fbd5e8e1d5 Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Fri, 6 Dec 2024 10:14:11 -0500
Subject: [PATCH 07/12] A few more nits
---
...4-12-04-differences-between-linting-and-type-checking.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index 177e0c921..baa0b578d 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -108,7 +108,7 @@ TypeScript is configured by a set list of compiler options on a project level.
Its [`tsconfig.json` ("TSConfig") files](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) allow for compiler options that change type checking for all files in the project.
Those compiler options are set by TypeScript and generally change large swathes of type checking behavior.
-ESLint on the other hand, runs with a configurable set of lint rules.
+ESLint, on the other hand, runs with a configurable set of lint rules.
Each lint rule can be granularly configured.
If you don't like a particular lint rule, you can always turn it off for a line, set of files, or your entire project.
@@ -144,12 +144,12 @@ By adding in rules from plugins, ESLint configurations can be tailored to the sp
ESLint and TypeScript operate differently and specialize in different areas of code defects.
Some code defects straddle the line between "best practices" and "type safety", and so can be caught by both linting and type checking.
-There are some core rules that are superseded by TypeScript's type checking.
+Those defects can often be caught by both ESLint and TypeScript.
To make the most of both tools, we recommend:
* In your ESLint configuration file, use the [ESLint `js.configs.recommended` config](https://eslint.org/docs/latest/use/getting-started#configuration), at least the [`tseslint.configs.recommended` configuration from typescript-eslint](https://typescript-eslint.io/getting-started/typed-linting), and any community plugins relevant to your project's libraries and frameworks
-* In your TypeScript configuration file, enable [`strict` mode](https://www.typescriptlang.org/tsconfig/#strict)
+* In your TypeScript configuration file, enable [`strict` mode](https://www.typescriptlang.org/tsconfig/#strict) to catch as many type safety issues as possible
typescript-eslint's recommended preset configs disable core ESLint rules that are not helpful with TypeScript.
The configs leave on any core ESLint rules that are useful alongside type checking.
From 7adb9d076c8a00fcb057d579c4c6125e19569e06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?=
Date: Mon, 9 Dec 2024 11:48:02 -0500
Subject: [PATCH 08/12] Apply suggestions from code review
Co-authored-by: Nicholas C. Zakas
---
.../2024-12-04-differences-between-linting-and-type-checking.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index baa0b578d..6686913c7 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -65,7 +65,7 @@ TypeScript does not attempt to enforce general best practices — only that valu
TypeScript won't detect likely mistakes that work within those types.
Linters, on the other hand, primarily target likely defects and can also be used to enforce subjective opinions.
-ESLint and other linters catch issues that are may or may not be type-safe but are potential sources of bugs.
+ESLint and other linters catch issues that may or may not be type-safe but are potential sources of bugs.
Many developers rely on linters to make sure their code follows framework and language best practices.
For example, developers sometimes leave out the `break` or `return` at the end of a `switch` statement's `case`.
From d4d9bc1f888b0f59e8a3792105ae000b51d5bf5e Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Mon, 9 Dec 2024 11:51:30 -0500
Subject: [PATCH 09/12] Trim down and specify type checking
---
...-12-04-differences-between-linting-and-type-checking.md | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index 6686913c7..5dd069f8e 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -57,11 +57,10 @@ logUppercase(9001);
Compiled languages such as Java and Rust perform type checking as part of their compilation step.
Because JavaScript is an interpreted language, TypeScript is run separately.
-Type checkers generally do not attempt to look for defects that are only likely to occur.
-They generally only look for uses of code that are certainly wrong.
+TypeScript generally does not attempt to look for defects that are only likely to occur.
+It generally only looks for uses of code that are certainly wrong.
-Nor do type checkers enforce subjective opinions that might change between projects.
-TypeScript does not attempt to enforce general best practices — only that values are used in type-safe ways.
+Nor does the type checking in TypeScript enforce subjective opinions that might change between projects.
TypeScript won't detect likely mistakes that work within those types.
Linters, on the other hand, primarily target likely defects and can also be used to enforce subjective opinions.
From 029b74c048a772e745fe03419a68e1482b0037ba Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Mon, 9 Dec 2024 11:51:51 -0500
Subject: [PATCH 10/12] Trim down and specify type checking even more
---
.../2024-12-04-differences-between-linting-and-type-checking.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index 5dd069f8e..3c6c2eb7c 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -59,9 +59,7 @@ Because JavaScript is an interpreted language, TypeScript is run separately.
TypeScript generally does not attempt to look for defects that are only likely to occur.
It generally only looks for uses of code that are certainly wrong.
-
Nor does the type checking in TypeScript enforce subjective opinions that might change between projects.
-TypeScript won't detect likely mistakes that work within those types.
Linters, on the other hand, primarily target likely defects and can also be used to enforce subjective opinions.
ESLint and other linters catch issues that may or may not be type-safe but are potential sources of bugs.
From b4293d94557fe9597fd03aea82c015f76d26b0d4 Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Mon, 9 Dec 2024 12:10:41 -0500
Subject: [PATCH 11/12] good chance
---
.../2024-12-04-differences-between-linting-and-type-checking.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index 3c6c2eb7c..b28f84bb5 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -10,7 +10,7 @@ tags:
- Linting
---
-If you're a JavaScript developer today, you're probably using ESLint and/or TypeScript to assist development.
+If you're a JavaScript developer today, there's a good chance you're using ESLint and/or TypeScript to assist development.
Those two tools are common examples of their kind of tooling: ESLint is a common *linter*, whereas TypeScript is a common *type checker*.
Linters and type checkers are two kinds of tools that both analyze code and report on detected issues.
From cec8a698038ce4f6c5a98f7cd8b468bc344db958 Mon Sep 17 00:00:00 2001
From: Josh Goldberg
Date: Mon, 9 Dec 2024 12:45:54 -0500
Subject: [PATCH 12/12] Small bits of proofreading
---
...4-12-04-differences-between-linting-and-type-checking.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
index b28f84bb5..85e910fd0 100644
--- a/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
+++ b/src/content/blog/2024-12-04-differences-between-linting-and-type-checking.md
@@ -26,7 +26,7 @@ As such, dynamic analysis brings with it the inherent danger of executing malici
Static analysis can be immensely helpful for improving code readability, reliability, and overall quality.
Many developers rely on static analysis to enforce consistent code formatting and style, to ensure code is well-documented, and to catch likely bugs.
-Because static analysis runs on source code, it can suggest improvements in editors, as code is written.
+Because static analysis runs on source code, it can suggest improvements in editors as code is written.
We'll focus in this blog post on ESLint and TypeScript:
@@ -145,7 +145,7 @@ Those defects can often be caught by both ESLint and TypeScript.
To make the most of both tools, we recommend:
-* In your ESLint configuration file, use the [ESLint `js.configs.recommended` config](https://eslint.org/docs/latest/use/getting-started#configuration), at least the [`tseslint.configs.recommended` configuration from typescript-eslint](https://typescript-eslint.io/getting-started/typed-linting), and any community plugins relevant to your project's libraries and frameworks
+* In your ESLint configuration file, use the [ESLint `js.configs.recommended` config](https://eslint.org/docs/latest/use/getting-started#configuration), at least the [`tseslint.configs.recommended` config from typescript-eslint](https://typescript-eslint.io/getting-started/typed-linting), and any community plugins relevant to your project's libraries and frameworks
* In your TypeScript configuration file, enable [`strict` mode](https://www.typescriptlang.org/tsconfig/#strict) to catch as many type safety issues as possible
typescript-eslint's recommended preset configs disable core ESLint rules that are not helpful with TypeScript.
@@ -174,7 +174,7 @@ declare function registerCallback(callback: Callback): void;
registerCallback((_, message) => console.log(message));
```
-Unused variables in JavaScript can also be caught by ESLint's [`no-unused-vars`](https://eslint.org/docs/latest/rules/no-unused-vars) rule; when in TypeScript code, the [`@typescript-eslint/no-unused-vars`](https://typescript-eslint.io/rules/no-unused-vars) is preferred instead.
+Unused variables in JavaScript can also be caught by ESLint's [`no-unused-vars`](https://eslint.org/docs/latest/rules/no-unused-vars) rule; when in TypeScript code, the [`@typescript-eslint/no-unused-vars`](https://typescript-eslint.io/rules/no-unused-vars) is preferable instead.
The lint rules by default also ignore variables whose name begins with `_`.
They additionally ignore parameters that come before any parameter that is itself used.