惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Simon Willison's Weblog
Simon Willison's Weblog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
Last Week in AI
Last Week in AI
月光博客
月光博客
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
U
Unit 42
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
H
Hacker News: Front Page
Recent Announcements
Recent Announcements
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
小众软件
小众软件
P
Palo Alto Networks Blog
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest
S
Secure Thoughts
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
O
OpenAI News
S
Securelist
云风的 BLOG
云风的 BLOG
H
Help Net Security
T
Troy Hunt's Blog

Prettier Blog

Prettier 3.9: Major parser upgrades and Formatting improvements Prettier 3.8: Support for Angular v21.1 Prettier 3.7: Improved formatting consistency and new plugin features! Prettier 3.6: Experimental fast CLI and new OXC and Hermes plugins! Prettier 3.5: New objectWrap option, experimentalOperatorPosition option and TS config file support! Prettier 3.4: A lot of bug fixes Prettier 3.3: New Flow features and a lot of bug fixes Prettier 3.2: Support JSONC and Angular’s ICU expression Prettier's CLI: A Performance Deep Dive $20k Bounty was Claimed! Prettier 3.1: New experimental ternaries formatting and Angular control flow syntax! Prettier 3.0: Hello, ECMAScript Modules! Prettier 2.8: improve --cache CLI option and TypeScript 4.9 satisfies operator! Prettier 2.7: new --cache CLI option and TypeScript 4.7 syntax! Prettier 2.6: new singleAttributePerLine option and new JavaScript features! Prettier begins paying maintainers Prettier 2.5: TypeScript 4.5 and MDX v2 comment syntax! Prettier 2.4: new bracketSameLine option and TypeScript 4.4 support! Prettier 2.3. In which assignments are consistent, short keys non-breaking, and Handlebars official Prettier for Ruby goes v1.0 🎉
A curious case of the ternaries
Alex Rattray · 2023-11-13 · via Prettier Blog

Ternary formatting has always been a challenge, and we're finally addressing it in v3.1.0 with the introduction of a novel formatting style.

Read on for our journey and the motivation behind this change, along with early developer feedback and an overview of the "curious ternaries" style.

Please give the --experimental-ternaries option a try and let us know what you think!

For a quick tl;dr, see the release post.

Introduction

Formatting nested ternaries nicely in a wide variety of scenarios is a surprisingly tricky challenge.

Developers have long found them so confusing to read that they end up just refactoring their code to an ugly series of if-else statements, often with a let declaration, an iife, or a separate function entirely.

According to beta testers, the new formatting style we've developed can take some getting used to, but ultimately allows ternaries to be practically used as a concise form of if-else-expressions in modern codebases.

Historical background

Prettier's original, naïve approach – just add indentation to each level of a nested ternary – worked fine in simple cases, but obviously doesn't scale to long chains of nested ternaries and had other problems.

So in 2018, we replaced that with flat ternaries, which seemed like a good idea at the time, but was not received well – the issue asking it to be reverted had well over 500 upvotes.

While we did ultimately revert back to indented ternaries, we wanted to find a better way.

Over the last few years, we explored and experimented with many, many possible solutions which would be as readable as indented ternaries in common cases, but also scale to work well in a wider variety of situations.

Challenging criteria

Ideally, we'd find one scheme that would meet our criteria:

  1. In all cases, it should be easy to follow "what's the if", "what's the then", and "what's the else" – and what they map to.
  2. The code should fluidly flow from a single ternary, to a chain of 2, to a long chain of simple cases, to something more complex with a few nested conditions. (Most alternatives we explored failed this test).
  3. The syntax in JSX, TypeScript conditional expressions (which cannot be expressed with if), and normal JS should all look and feel the same.
  4. It should scale to nested ternary chains of arbitrary length (imagine a TypeScript conditional type with dozens of alternative cases).

Indented ternaries clearly failed (4), arguably (1), and even (3) – we have almost always printed JSX ternaries in a flat-but-readable format that unfortunately felt unnatural outside of JSX.

Many people in the community were excited about a "case-style", drawing inspiration from the match syntax from languages like Rust or OCaml, but it did not meet (2) and other goals.

A surprising solution

The good news is that we found a formatting algorithm that met our criteria. The bad news is that it's novel, and thus unfamiliar to most developers.

In beta testing this feature, we found developers were quite skeptical when they first saw it:

"I'm not convinced the new version is simpler to read here."

But then, after using it for a bit, they didn't want to go back:

"I'm liking the ternaries! I think it makes sense to have them formatted like this. I also got used to them quite quickly as well. \nI agree with this, it takes a very short time to get used to it."

Another developer had this to say:

My first hour with the rule on, it felt a little odd. But by hour two, I’d used it a few times to solve problems that otherwise would have been ugly refactors to if statements. I’m not going back.

I used to hate nested ternaries, but I also hate restructuring a nice line of code into if-else statements. The new rule adds an understandable, linear if-else, if-else expression to the language and is much nicer than multiple ternaries as nested branches.

So we felt we had a winning formula, but we knew it could be a jarring introduction to the community.

As a result, we decided to put this new formatting behind a temporary --experimental-ternaries option for a few months, and in the meantime go ahead and ship what the community has been clamoring for: indented ternaries.

Styling Overview

So what does this new style look like, anyway?

Here's a quick, contrived example to show the thinking behind "curious" ternaries:

const animalName =

pet.canBark() ?

pet.isScary() ?

'wolf'

: 'dog'

: pet.canMeow() ? 'cat'

: 'probably a bunny';

  1. Every line that ends with a question mark is an "if".
    • If you see foo ? it's like asking a question about foo – "if foo? then, …".
  2. Every line that starts with a : is an "else".
    • If you see : foo that means, "else, foo".
    • If you see : foo ? that means "else, if foo?".
  3. Every line without : or ? is a "then".
    • If you just see foo, that means, "then foo".

And here's the code rewritten to demonstrate "case-style" ternaries:

const animalName =

pet.isScary() ? 'wolf'

: pet.canBark() ? 'dog'

: pet.canMeow() ? 'cat'

: 'probably a bunny';

You can see this is a nice concise way to get something approaching match-style syntax in JavaScript, with just the humble ternary operator (albeit missing several features).

Our new formatting is a fluid blend of "curious" ternaries (where the question mark is always at the end of the line), and "case-style" ternaries, where the question mark is in the middle of the line.

For example:

const animalName =

pet.canSqueak() ? 'mouse'

: pet.canBark() ?

pet.isScary() ?

'wolf'

: 'dog'

: pet.canMeow() ? 'cat'

: pet.canSqueak() ? 'mouse'

: 'probably a bunny';

Give us your feedback!

We hope you like the more readable new default, and we really hope you give the new --experimental-ternaries option a try for a few weeks and let us know what you think.

Please give us feedback via Google Forms: https://forms.gle/vwEuboCobTVhEkt66