Ryan Cavanaugh 👉 searyanc.dev on bsky Profile picture
Engineering lead for @typescript. Now at https://t.co/uvEAuNf1VJ
Jul 5, 2022 10 tweets 2 min read
Incompleteness is when your program works, but the computer doesn't believe you. This is a necessary part of all type checkers due to Math (see Gödel, 1931), and also often for performance reasons

A common source of incompleteness in TypeScript is ... 🧵 When your program contains some small possible set of values for some input, and it can be seen that your program works for each possible value, then your program should be OK?
Feb 23, 2022 11 tweets 2 min read
JavaScript performance is bananas, a thread.

Let's write a function to sum the values from a the 'val' property of each element in an array:

function sum(arr) {
let acc = 0;
for (let i = 0; i < arr.length; i++) {
acc += arr[i].val;
}
return acc;
}

1/10 We'll make two arrays and put 100 million copies of the exact same object into them...

const array1 = [];
const array2 = [];
const s = { val: 1 };
for (let i = 0; i < 100_000_000; i++) {
array1.push(s);
array2.push(s);
}

2/10
Feb 22, 2022 9 tweets 2 min read
Back in 1999 I played a lot of Starcraft online and was really annoyed by the "Big Game Hunters" mode that was very popular at the time. This is the story of my first real computer program. 🧵/ I was also really into programming and fired up Spy++ with Starcraft running and noticed that the in-game lobby list was just a standard Win32 ListView. In fact, each game's metadata (map, settings, etc) was a different column!
Mar 3, 2021 7 tweets 2 min read
Here's a near-miss story about "why aren't there more women in tech". A woman I know joined a FAANG-level company fresh out of college, and was offered the choice of two teams. 1/ Team A worked in an area she was unfamiliar with and had no interest in, everyone on the team (all men) was two or more title levels above her, and had no suitable entry-level work

Team B was more balanced, and fit her interests and experience

She picked Team B 2/
Feb 23, 2021 17 tweets 2 min read
People sometimes point to JavaScript's hoisting of 'var' declarations as an oddity or a quirk. I actually disagree with this, and let me explain why. 🧵! Let's take a few givens (*) first:
Oct 1, 2020 14 tweets 3 min read
Let's dig in. Gary's discovery is thankfully easy to reproduce

let b: 1 | 2 = 3;

This indeed produces the error (under --target ES5)

Type '3' is not assignable to type '1 | 2'.

and with --target ES6:

Type '3' is not assignable to type '2 | 1'.

Cool, what the heck? First, background. TypeScript aggressively interns types during checking to save memory and improve performance. This means that there's only ever one type object (the internal representation) for the literal '1' and only ever one type object for the literal '2'
Sep 29, 2020 7 tweets 1 min read
I have come to grow weary of debug assertions. They're still a good idea, but it's rarely obvious in complex systems what kind of assertion is being made, and people tend to not leave good comments. A cataloging: 1/ A) I believe two different parts of this program behave in a way that produces an invariant, e.g.

const inThere = arr.includes(el);
if (inThere) {
const index = arr.indexOf(el);
assert(index >= 0);
}

n.b. this assert can fail
Sep 29, 2020 4 tweets 1 min read
I'm a huge fan of fire safety. Multiple well-signed exits, fire extinguishers everywhere, sprinklers, you name it. An under-rated aspect of modern life is that you're much, much less likely to die in a fire than you were fifty years ago.

However, it can go too far! 1/ In a fire, you need to get out in a hurry in poor conditions, so anything that stops quick exit is a danger. Doorknob manufacturers now make many of their locking doorknobs "free egress", which means the doorknob acts as if it's unlocked from the inside, even if it's locked 2/
Sep 2, 2020 4 tweets 1 min read
Lemon Spindrift (3 Calories / can) is just an infinitely more enjoyable beverage than Lemon La Croix (0 Cal / can). I don't think the 1g carbs is what makes the difference - more likely, the tradeoffs you have to make to get from 3 Cal to 0 Cal ruin the flavors as a side effect If you want a 0 calorie drink, water / mineral water are much better choices. If you want a lemon-flavored low-calorie beverage, Spindrift is way better. There's little reason to punish yourself by drinking Lemon La Croix; it's all downside for very little upside
Jul 24, 2020 8 tweets 2 min read
It's Friday so let's do a boring programming language design thread. How do function default argument values work? 1/ There are two popular strategies you can employ in your language:
* At the call site, substitute in the defaults for any missing arguments (let's call this "inline")
* In the function, detect missing arguments and substitute in the defaults (let's call this "preamble") 2/
Jul 20, 2020 6 tweets 2 min read
Fun find from Ben here. Anyway you've heard about "leaky abstractions"; this is sort of the converse problem, which is the "leaky sugar". 1/ 1. A programming language adds a new feature that is precisely syntax sugar for some existing operation
2. Developers use this in a way that implies a different higher-order operation
3. Unexpected results occur because a lower-level operation can't use higher-level invariants 2/
Apr 7, 2020 8 tweets 1 min read
A brief history of "What is the standup status order" on the TypeScript team (1/8) 1: Clockwise or counterclockwise, randomly, with the remote participants going wherever the TV was

Discarded because: doesn't work when everyone was remote
Mar 20, 2020 7 tweets 2 min read
People can get a little carried away with "consistency" when reasoning about what TypeScript does/doesn't consider to be worthy of a warning. Today's example

const obj = { ...x?.someObj }

This sometimes spreads in an 'undefined'. Is that OK? Is it "inconsistent" if it is? 1/ If you wrote

{ ...undefined }

Even though this is a no-op at runtime, it's definitely an error; this operation is meaningless and it would make no sense to do it unconditionally. People don't write code like this on purpose.
Mar 3, 2020 4 tweets 1 min read
FB is throwing literal millions of dollars at a Messenger rewrite to gain probably a few dozen milliseconds of startup time on potatophones and probably a few dozen seconds of initial download time on marginal 2G connections. 1/ Do those business requirements sound anything like yours? No? Then don't use their situation to make assumptions about React Native!

This is the kind of stuff you can worry about later once you have a bajillion dollars sitting around looking for problems you can throw $ at
Jan 16, 2020 4 tweets 1 min read
I deleted a tweet that was just a dumb joke because people were missing the point. If you see something weird that defies your expectation, shipped by a good team, you should legit be asking questions, because there's almost certainly a good reason behind it. Be curious! Why is checker.ts 35,000 lines long? It's not because the TypeScript team doesn't know that you can split code into separate files. It's weird, yes, but it's something you should be wanting to learn the motivations for.
Jan 7, 2020 5 tweets 1 min read
Here's a good question I just got. Let's say you have a type

type Foo = { x: Array<{ y: string }> };

We can refer to the type of 'x' by Foo['x'], but how do we refer to the type of 'y' ? The answer may be surprising: Foo['x'][number]['y'] -- this seems to be a mismash of different syntaxes, mixing up property names and types, right?

It's not!
Jan 2, 2020 6 tweets 2 min read
JS library behavior is impossible, chapter 836: Someone wants to update the type definition of this function to explicitly accept 'null' in the first argument github.com/kahwee/truncat…

Is this a correct change to the types? 1/ The documentation says it accepts "a string", not "a string or null". But the code explicitly checks for null (*not* undefined) and bails out early. BUT the code also coerces all the positional arguments to integers.

SO I HAVE NO IDEA. 2/
Dec 16, 2019 8 tweets 3 min read
Boot sole enthusiasts have been eager for "context" here, because SuReLy ThErE's A rEaSoN to use the "bump into someone's backpack" technique at the start of a legitimate arrest, & also question why someone was filming

SPD does not deserve the benefit of the doubt here. Thread / 2009: Seattle Police pay out $10M after an officer smashed the *wrong guy* into a wall, ultimately killing him. Let's be glad the woman in this clip seemed unharmed. seattletimes.com/seattle-news/c…
Nov 27, 2019 9 tweets 2 min read
#typescript time - there's some confusion between type errors and things that simply don't make sense.

The expression `(3 + 5) * 0` isn't something that makes sense to write in a program, because multiplication by zero has a known result. But it's not a type error! It's outside the scope of a type system to warn you about this "error" - the operands have meaningful inputs and well-defined outputs, even if the fact that you wrote it at all seems suspicious.

Not every expression you can write with valid inputs is a good one.
Nov 20, 2019 6 tweets 4 min read
I spend all day every day telling people on GitHub that we're not doing features because it'd infringe on the TC39 committee's areas of ownership. "Taking over an open standard" is completely the opposite of what's happening. 1/? Here are some examples of user-demanded features that we explicitly didn't implement because we want the JS standards body to do them instead.

github.com/microsoft/Type…
github.com/microsoft/Type…
github.com/microsoft/Type…
github.com/microsoft/Type…
github.com/microsoft/Type…
Oct 23, 2019 4 tweets 2 min read
This thing is insane. You could be fooled if you weren't paying close attention. Image Have you ever felt seen by an AI? Image