44.3 TypeScript 4.9: satisfies Operator and auto-Accessors
Right, let’s talk about TypeScript 4.9. This was one of those releases that didn’t shake the earth, but instead gave you a few genuinely useful tools to stop banging your head against the type system. The two big ones were the satisfies operator and auto-accessors. One solves a problem you’ve definitely had, the other solves a problem you probably didn’t even know you could have.
The satisfies Operator: Your New Best Friend
You’ve been here before. You need an object to have specific values, but you also want TypeScript to remember the literal types of those values, not just widen them to string or number. Before satisfies, you had two equally annoying options.
Option 1: Type Annotation (The Bad Way)
type Colors = "red" | "green" | "blue";
const myColors: Record<string, Colors> = {
primary: "red", // TypeScript now thinks myColors.primary is just `Colors`
accent: "blue",
warning: "yellow" // This is great! It correctly errors: Type '"yellow"' is not assignable to type 'Colors'.
};
const primaryHex = getHexCode(myColors.primary); // Error! getHexCode expects a literal, not just `Colors`.
Option 2: “As Const” and Hope for the Best (The Worse Way)
const myColors = {
primary: "red",
accent: "blue",
} as const;
const primaryHex = getHexCode(myColors.primary); // Works! Type is "red"
// But wait, we lost all our safety.
myColors.warning = "yellow"; // No error, because we didn't define the type structure upfront. Disaster.
Enter satisfies. It’s the Goldilocks solution. It validates that your object satisfies a type without erasing the precious literal types of its properties.
type Colors = "red" | "green" | "blue";
const myColors = {
primary: "red", // Type is "red", not just `Colors`
accent: "blue", // Type is "blue"
warning: "yellow" // ERROR: Type '"yellow"' is not assignable to type 'Colors'.
} satisfies Record<string, Colors>;
// Now we get both!
const primaryHex = getHexCode(myColors.primary); // Works perfectly, type is "red"
It’s like telling TypeScript, “Hey, check this object against this type to make sure it’s valid, but for the love of god, don’t throw away the specific information you just learned about it.” It’s the validation of a type annotation with the inference power of as const. Use it for configuration objects, theme definitions, or any place where you care about both the shape and the specific values.
auto-Accessors: A Glimpse into the Future
Now, this one is a bit more niche, and honestly, it’s less about solving a problem today and more about laying the groundwork for a future feature. autoAccessors is an ECMAScript proposal that TypeScript implemented behind a flag (useDefineForClassFields must be enabled).
Here’s the classic problem it (will) solve. You have a class field that you want to have some logic around when it’s get or set.
The Old, Verbose Way:
class MyClass {
private _value: number = 0;
get value() {
console.log("Getting value!");
return this._value;
}
set value(newVal: number) {
console.log("Setting value!");
this._value = newVal;
}
}
autoAccessors let you declare this more concisely, similar to how other languages like C# do it.
class MyClass {
accessor value: number = 0;
// Under the hood, TypeScript transforms this into:
// private __value: number = 0;
// get value() { return this.__value; }
// set value(newVal: number) { this.__value = newVal; }
}
“But wait,” you ask, “where’s the logging? This seems pointless!” And you’d be right. The current implementation is basically syntax sugar that creates a trivial getter/setter pair. The real power is coming later with the ECMAScript proposal, which will allow decorators to intercept access to these accessor fields. That’s the killer feature. You’ll be able to do:
class MyClass {
@logged // (Hypothetical future decorator)
accessor value: number = 0;
}
And have the @logged decorator automatically wrap the getter and setter with your logging logic. For now, it’s a bit of a solution in search of a problem, but it’s good to be aware of it because this is where the language is headed. Enable the flag, play with it, and get ready for the decorator-powered future.
So there you have it. satisfies is an immediate, must-use tool for writing cleaner, safer code. autoAccessors is a down-payment on a future where class fields become a lot more powerful. TypeScript 4.9: giving you practical solutions today and a sneak peek at the clever stuff coming tomorrow.