01 Apr 2022
A little TypeScript puzzle I encountered recently:
interface Valid {
readonly isValid: true;
}
interface Invalid {
readonly isValid: false;
message: string;
}
type Validation = Valid | Invalid;
function report(validation: Validation) {
if (!validation.isValid) {
console.error("Invalid", validation.message);
}
console.info("Valid");
}
Looks fine right? And the TypeScript playground has no problem with
it.
But in my local environment, it was complaining that the message
property
didn’t exist on validation
, despite the fact that validation
should be
narrowed to Invalid
in the if
branch.
15 Feb 2022
I wrote something a while back about typesafe
builders (builders
which let you add information in any order you like, but fail to compile if you
try and build the result without having added all the required information). The
implementation was in Java, so I used subtyping to represent types that do
include information, don’t include information, or are indifferent to whether
they include information. But I’ve been wondering, how would you implement this
in a language without subtyping? It turns out one answer is generalised abstract
data types (GADTs).
08 Jan 2022
Aspect-oriented programming is still a fairly popular programming tool. The idea
is to reduce the coupling, and increase the modularity, of programs by providing
“aspects” to handle “cross-cutting concerns” separately, rather than
intermingling these concerns with each other and with a program’s specific
business logic. The problem with this approach is that cross-cutting concerns,
in the way required by aspect-oriented programming, are vanishingly rare.
13 Feb 2021
You learn about clever purely-functional abstractions and you think, neat, but
not really relevant to everyday programming; then the next thing you know,
you’re implementing a fairly boring bit of business logic and you think, dammit,
what I really need here are profunctor optics.
Mainstream programming languages now generally include some support for
functional idioms: first-class functions, map, maybe fold. The idea seems to be
to introduce functional features to be used when they are convenient, but to
avoid the more complicated functional abstractions. This usually turns out to
mean writing functional code mostly at a small scale.
24 Oct 2020
Mingus believes now that it got too far away from jazz – spontaneity – since
almost all of the music was written. He remembers one rehearsal at which Teddy
had left several bars open for blowing and everyone jumped on him with ‘Man,
are you lazy? Write it out!’
Dependency injection is a great idea. Supplying dependencies to a class, rather
than having the class create them themselves, is a practical illustration of
the benefits of the single-responsibility principle. Creating dependencies is a
different responsibility from using them, and the class that uses dependencies
probably doesn’t (or shouldn’t) have the information required to create the
dependencies; so you can isolate this responsibility by in a separate class (or
multiple classes, for different environments or for testing) by injecting the
dependencies. But dependency injection doesn’t require a framework, and indeed
dependency injection frameworks are useless if they’re not actively harmful;
their continued prevelance is the zombie-like persistence of a dead
ideology.