@let and the Modern Template Expression In short: Angular templates deliberately did not let you write much code. That was right. But the limits were tighter than they needed to be, and v19 to v22 loosened the ones that only ever caused workarounds. The guiding idea has not changed: logic belongs in the class, not the template. What changed is that a few reasonable things were impossible for no good reason. — naming a value (v19) There was no way to give a name to a value inside a template. Both workarounds were bad: names the value without changing what shows: The rules: You cannot change it. It is a name for an expression, not a variable you assign to. It updates on its own when the values it uses change. It only works inside its block , and only below the line that declares it. It is genuinely useful inside , where you would otherwise repeat work on every row: One warning: makes it easy to put real logic in templates, and that is a step backwards. is fine — it names a condition used twice. A with three nested question marks belongs in a . Spreading objects and arrays (v21.1) Before this you had to add a on the class just to join two objects together. Small inline functions (v21.2) Templates could not define functions, so any callback needing a parameter had to be a class method: The main use is passing simple test functions to components that accept them. Use this carefully. A function written in a template is created fresh each time, so passing one to an child means that input looks different every cycle. For a simple comparison this is harmless. For anything the child remembers between updates, use a or a class field instead. checks (v21.2) Angular now understands the type inside each branch. Before this you needed a marker field on the object or a helper method on the class. Complete checks (v21.2 / v22) This is really a type-checking feature rather than a display one: This fails to build , because is not handled. Add a new state later and every template that claims to be complete tells you about it immediately — instead of leaving a blank space on screen. v22 adds to check against a named value. Optional chaining now returns (v22) A small correctness fix that can change behaviour: in templates now gives instead of when it stops early, matching TypeScript. If you have code that specifically checks for coming out of a template — most likely a custom pipe with a branch — check it. In practice almost nothing depends on this, but it is a real change rather than an addition. Comments inside an element (v22) Before, a comment had to sit above the whole element, which was awkward when it applied to one attribute. The rule that still holds None of these change the underlying idea: templates describe what to show. The class decides what is true. naming a value used twice is describing. A template working out a discount level is deciding, and that belongs in a where it can be tested. The reliable test is testability. A can be tested on its own. Logic inside a template can only be tested by drawing the component and reading the page. When you find yourself writing something you would want a test for, that is the line. The architect's view These additions create a governance problem, and it is worth getting ahead of. Each one removed a specific workaround. Together they make it possible to put a lot more logic in templates than before — and template logic is the least testable, least reviewable code in an Angular application. is the one to watch. is naming a condition used twice: good. A chaining three conditions together is business logic that has escaped the class, where no unit test can reach it. Set the line explicitly for your team: if you would want a test for it, it is a . That is a rule a reviewer can apply without arguing about taste. The one addition that improves quality rather than convenience is . Everything else here saves typing. This catches bugs at build time. Add a state to that union six months from now, and every template claiming to handle all of them fails to compile. Without it, you get a blank area of the screen in production and a support ticket. That is worth adopting as a standard anywhere you switch on a fixed set of values — order states, roles, payment methods. The cost is one line. The benefit is that a whole class of "we forgot to handle the new case" bugs becomes impossible. On the v22 optional-chaining change. now yields rather than when it stops early, matching TypeScript. This is the only change in this lesson that can alter existing behaviour, so it is worth a targeted check for code that explicitly tests template output for — most likely a custom pipe. Rare, but real. Mentoring note. Teach alongside its limit, in the same breath. Introduced on its own it reads as "you can write code in templates now," which is the wrong lesson and hard to walk back later. Cheat sheet Do and don't: Recap gives you a named, read-only, self-updating value inside a template block. It replaces two…