6
[Code] Ternary-based pattern matching in JS - KaKi's blog
blog.kaki87.net# Ternary-based pattern matching in JS Folks are jealous of other programming
languages having this kind of pattern matching abilities : kotlin fun
compareNumbers( a: Int, b: Int ) = when { a > b -> "A is greater than B" b > a
-> "B is greater than A" else -> "A and B are equal" } But, so do we :
typescript const compareNumbers = ( a: number, b: number ) => a > b ? 'A is
greater than B' : b > a ? 'B is greater than A' : 'A and B are equal'; And this
example is at identical character count btw. For example, I use it here
[https://git.kaki87.net/KaKi87/dynapt/src/commit/9c89046de317295d7cd2e20e96b1a877a7ccfc72/src/updatePackages.js#L42-L44]
in dynapt(1) : javascript url = app.url ? app.url : app.github ?
`https://api.github.com/repos/$%7Bapp.github.repo%7D/releases/latest` :
undefined To define an app download url that is either already provided if
arbitrary, or requires being generated if from a GitHub / string. I
use it again in the same file a little lower
[https://git.kaki87.net/KaKi87/dynapt/src/commit/9c89046de317295d7cd2e20e96b1a877a7ccfc72/src/updatePackages.js#L64-L66]
: javascript isUnmodified = app.url ? response.status === 304 : app.github ?
response.status === 304 || cache[app.id]?.id === response.data['id'] :
undefined; To determine whethere the download file from the abovementioned URL
is modified or not, which works a little differently for GitHub because of its
API. In another project that uses Discord.JS and TypeScript, I use this syntax
for a conditional return type : typescript createSelectRow = ({ type // ... }: { type: type, // ... })
: type extends 'channel' ? ActionRowBuilder : type
extends 'role' ? ActionRowBuilder : type extends 'user' ?
ActionRowBuilder :
ActionRowBuilder => { // ... } Etc. — (1) dynapt is a
dynamic APT repository. More information about that project here
[https://gist.github.com/KaKi87/f620788e9901abbfef4978eb7ad358b4].
Interesting and valid point, but Kotlin’s
when
is not actually pattern-matching. It really is just syntactic sugar for if-else, like you’ve demonstrated.Actual pattern-matching allows matching on the structure of a data type. So, you formulate a pattern to describe the structure and then you can choose different code paths based on whether the pattern matches or you can also access fields inside of this data type.
Rust allows pattern-matching even in variable assignments, which is going to look funky, but I think it shows quite well that pattern-matching isn’t just a fancy
switch
statement: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=3a8d126fa0cb9736597793915b00dd5dSo what happens is that:
When someone writes this in Rust:
let x = 1;
It’s still pattern matching under the hood, but the pattern
x
is just a singular wildcard, so the right-hand side just gets ‘assigned’ to that variable name.And with these simple examples, you might think that being able to access field values this way is silly, since you can also access them via
my_data_type.foo
, but it becomes more useful with deeply nested data types, and in particular in statically typed languages, it allows you to work with different data types without type casting. So, it would be more useful of a feature for TypeScript than it might be for JavaScript.That’s a condition, so it can fit in a ternary.