diff --git a/website/public/blog/version-3.0/index.ejs.html b/website/public/blog/version-3.0/index.ejs.html new file mode 100644 index 0000000000..67c85fb020 --- /dev/null +++ b/website/public/blog/version-3.0/index.ejs.html @@ -0,0 +1,390 @@ + + + + + + + + <%- await include("../../common-head.ejs.html") %> <%- await + include("../blog-head.ejs.html") %> + + + + + <% function callsToAction() { %> + + <% } %> + +
<%- await include("../../common-nav.ejs.html") %>
+ +
+

<%= meta.title %>

+

+ +

+ quick-lint-js is a JavaScript bug finder. Today, version 3.0 makes it + also a TypeScript bug finder! quick-lint-js complements TypeScript with + beginner-friendly messages and + fast linting. +

+ + <%- callsToAction() %> + +

+ Example code used in this article has been adapted from various open + source projects, including some Copyright Tiny Technologies, Inc. and + Copyright Elasticsearch B.V. +

+ +
+

Beginner friendly

+ +

+ My goal in developing quick-lint-js is to make JavaScript (and + TypeScript) easier for beginners to learn by catching their silly + mistakes. +

+ +

+ TypeScript's compiler already catches coding mistakes for you. Its + fantastic Visual Studio Code extension is the main reason behind its + popularity. However, TypeScript is not easy. It has over 80 keywords + and many archaic features for compatibility with Node.js, browser, and + JavaScript. +

+ +

+ What can quick-lint-js do that TypeScript's extension and compiler + can't? Let's walk through some examples. +

+ +

Keyword confusion

+ +

+ I am dyslexic, so sometimes simple issues are hard for me to notice. + Can you tell what's wrong with the following code by looking at + TypeScript's error messages? Hint: + I often confuse different keywords which start with the same + letter. +

+ +
+
+
TypeScript
+
+
it('matches on first word', await () => {
+  await table.searchForItem('Hello');
+  await table.expectItemsCount('vis', 1);
+});
+

+ Expression expected. (1109)
+ ',' expected. (1005)
+ ':' expected. (1005)
+ ',' expected. (1005)
+ ':' expected. (1005)
+ ',' expected. (1005) +

+
+
+
+
quick-lint-js
+
+
it('matches on first word', await () => {
+  await table.searchForItem('Hello');
+  await table.expectItemsCount('vis', 1);
+});
+

+ 'await' cannot be followed by an arrow function; use 'async' + instead [E0178] +

+
+
+
+
+ +
+

TSX is not a TypeScript superset

+ +

+ TSX is TypeScript with JSX (React) extensions. JSX is a + backwards-compatible extension to JavaScript, so naturally TSX is a + backwards-compatible extension to TypeScript, right? +

+ +

+ Unfortunately, some valid TypeScript code is not valid TSX. If you + copy-paste code from a .ts file to a + .tsx file, you might be in for a surprise: +

+ + +
+
+
TypeScript
+
+
const trim = <T>(f: (a: T) => boolean) => {
+  return (arg1: any, arg2: T) => {
+    return f(arg2);
+  };
+};
+

+ Cannot find name 'T'. (2304)
+ JSX element 'T' has no corresponding closing tag. (17008)
+ Unexpected token. Did you mean `{'>'}` or `&gt;`? + (1382)
+ Unexpected token. Did you mean `{'>'}` or `&gt;`? + (1382)
+ Expression expected. (1109)
+ Unexpected token. Did you mean `{'>'}` or `&gt;`? + (1382)
+ Expression expected. (1109)
+ Unexpected token. Did you mean `{'}'}` or `&rbrace;`? + (1381)
+ Unexpected token. Did you mean `{'}'}` or `&rbrace;`? + (1381)
+ '</' expected. (1005) +

+
+
+
+
quick-lint-js
+
+
const trim = <T>(f: (a: T) => boolean) => {
+  return (arg1: any, arg2: T) => {
+    return f(arg2);
+  };
+};
+

+ generic arrow function needs ',' here in TSX [E0285] +

+
+
+
+
+ +
+

JSX is not HTML

+ +

+ In HTML, whitespace is mostly unimportant, and elements can be placed + side-by-side naturally. JSX mimics HTML but is its own language with + its own quirks, including JSX fragments and JavaScript's famous + ASI. +

+ +

+ When you make a mistake with JSX, TypeScript does tell you about it, + but a beginner might not know how to fix the problem. quick-lint-js + gives you better hints so you can quickly fix your code: +

+ +
+
+
TypeScript
+
+
export function Spacer() {
+  return
+    <EuiSpacer size="xs" />
+    <EuiHorizontalRule margin="none" />
+    <EuiSpacer size="xs" />
+}
+

+ Unreachable code detected. (7027)
+ JSX expressions must have one parent element. (2657) +

+
+
+
+
quick-lint-js
+
+
export function Spacer() {
+  return
+    <EuiSpacer size="xs" />
+    <EuiHorizontalRule margin="none" />
+    <EuiSpacer size="xs" />
+}
+

+ return statement returns nothing (undefined) [E0179]
+ missing '<>' and '</>' to enclose multiple + children [E0189] +

+
+
+
+
+ +
+

Emoji...⁉️

+ +

+ Since its iPhone debut in 2008, emoji has been the primary method of + communication among zoomers. What better place than TypeScript + variable names for our favorite emotive icons? Sadly, the designers of + TypeScript (and JavaScript) don't let us have fun. 🙁 +

+ +
+
+
TypeScript
+
+
let 💩 = 'TypeScript';
+

+ Cannot find name 'let'. (2304)
+ Variable declaration not allowed at this location. (1440)
+ Invalid character. (1127)
+ Declaration or statement expected. (1128)
+ Declaration or statement expected. (1128) +

+
+
+
+
quick-lint-js
+
+
let 💩 = 'TypeScript';
+

+ character is not allowed in identifiers [E0011] +

+
+
+
+ +

+ Excited to try quick-lint-js? Installation couldn't be simpler! No + package.json nonsense or config file headaches. Just plug + quick-lint-js into your editor and it works: +

+ + <%- callsToAction() %> +
+ +
+

Fast linting

+ +

+ quick-lint-js's name would be nonsense if it wasn't + quick. How quick is quick? + Beyond human perception. + + + + <%- callsToAction() %> +

+
+ +
+

What's next?

+ +

+ What is in quick-lint-js's future for version 4.0? I am going to play + with Vue in 2024, so implementing + Vue SFC in quick-lint-js + (and also Svelte and plain HTML) sounds like the perfect next step. + While focusing on TypeScript, I accumulated a big + backlog of tiny bugs, and also thought of some + easy-to-implement lint rules. +

+
+ +

+ quick-lint-js version 3.0 has over 3000 patches since version 2.0. + Over 70 people + made quick-lint-js possible. +

+ +

+ Press release written by strager, + lead developer of quick-lint-js. +

+ + +
+ + + + + + diff --git a/website/public/main.css b/website/public/main.css index bbd640b303..0cdfb295db 100755 --- a/website/public/main.css +++ b/website/public/main.css @@ -392,12 +392,21 @@ pre mark, text-decoration-skip-ink: none; text-decoration-style: wavy; } +pre mark:empty { + --svg-height: 4px; + background: none; + display: inline-block; + height: 1em; + height: calc(1lh + var(--svg-height)); + margin-left: -2px; /* (width of SVG) / 2 */ + position: absolute; + width: 6px; +} pre mark:empty::before { color: red; content: url("demo/carat.svg") / "^"; content: url("demo/carat.svg"); - margin-left: -2px; /* (width of SVG) / 2 */ - margin-top: 4px; /* height of SVG */ + margin-top: var(--svg-height); position: absolute; } @media (prefers-color-scheme: dark) { @@ -800,7 +809,9 @@ kbd.keystroke { #editors-support img { padding-bottom: 1rem; } +} +@media only screen and (max-width: 46em) { .eslint-comparison { border-bottom: solid 1px #aaaa; grid-template-areas: "eslint" "qljs";