Use C# 14 extension properties only where your own code reads them
C# 14 lets you add a property to a type you don't own, and at the call site it looks like a real one. It compiles to a static method, so EF Core can't use it in a query (the compiler refuses it with CS9296), System.Text.Json doesn't write it, and reflection on the type doesn't list it. Keep them for reads in your own code, and give queries an expression instead.
An Angular upload progress bar that shows the server is still working
An upload bar that says 100% and then sits still while the server works looks frozen. Switch to a processing state when the last byte leaves the browser, then draw it however you like: six designs on one signal state.
Return a C# 15 union type instead of a Result class
C# 15 adds union types: a closed set of case types, implicit conversions from each one, and a switch the compiler checks for missing cases. For a service method with a few outcomes it reads better than a hand-written Result class. Keep it out of JSON for now: RC1 writes no case marker, and a plain read can't tell two object cases apart.
How to validate conditional fields in Angular Signal Forms
Signal Forms skip the validators on hidden and disabled fields, so a form with a conditional section can report valid() while a required field in the model is empty, or still holds an address the user backed out of. Build the object you send from the form state and leave the hidden sections out of it.
Deterministic cleanup in TypeScript with await using and DisposableStack
using and await using close a resource when the block ends, whether it ends normally or by throwing, and they close several resources in reverse order of opening. Three nested try/finally blocks become three lines, DisposableStack covers the case where the count is only known at run time, and a cleanup that throws gives you a SuppressedError whose two fields are easy to read backwards.
Wrap Tom Select in an Angular signal form without the change-event loop
Angular 22 asks a custom form control for one thing, a value model signal. Wrapping Tom Select in that contract takes about twenty lines, and then the widget starts answering the writes your own code makes. The change event fires for programmatic writes and user picks alike, silent suppresses it, and item_add is not covered by silent at all.
linkedSignal: a derived value you can also write to
A computed signal is read-only, so a derived value the user can also change gets copied into a plain signal with an effect to reset it. linkedSignal is the writable one, and the rule for when your write survives is worth knowing exactly: it stands until something the computation reads changes, and it is dropped the moment that happens, which you observe on the next read.
Use satisfies to check a config object without widening its types
Annotating a config object checks it and then replaces what you wrote with the type you checked against. satisfies runs the same check and leaves your types alone — so ink is still a string, the colour is still a tuple, and a typo in a key is still an error.
What track $index actually costs in Angular's @for
track $index is usually described as the slow option. Measured, it is often the cheap one — a prepend costs it the same single DOM insertion, and a shuffle costs it zero structural DOM work. What it costs is correctness: every row's half-typed input and component state slides onto the row next door.
Replace isLoading, error and data with one discriminated union
isLoading, error, data — three flags, eight combinations, half of them lies. Discriminated unions make the impossible states impossible, and the compiler enforces it.