Posts Tagged ‘ChristianWörz’
[DevoxxBE2023] A Deep Dive into Advanced TypeScript: A Live Coding Expedition by Christian Wörz
Christian Wörz, a seasoned full-stack engineer and freelancer, captivated the Devoxx Belgium 2023 audience with a hands-on exploration of advanced TypeScript features. Through live coding, Christian illuminated powerful yet underutilized constructs like mapped types, template literals, conditional types, and recursion, demonstrating their practical applications in real-world scenarios. His session, blending technical depth with accessibility, empowered developers to leverage TypeScript’s full potential for creating robust, type-safe codebases.
Mastering Mapped Types and Template Literals
Christian kicked off with mapped types, showcasing their ability to dynamically generate type-safe structures. He defined an Events
type with add
and remove
properties and created an OnEvent
type to prefix event keys with “on” (e.g., onAdd
, onRemove
). Using the keyof
operator and template literal syntax, he ensured that OnEvent
mirrored Events
, enforcing consistency. For instance, adding a move
event to Events
required updating OnEvent
to onMove
, providing compile-time safety. He enhanced this with TypeScript’s intrinsic Capitalize
function to uppercase property names, ensuring precise naming conventions.
Template literals were explored through a chessboard example, where Christian generated all possible positions (e.g., A1
, B2
) by combining letter and number types. He extended this to a CSS validator, defining a GapCSS
type for properties like margin-left
and padding-top
, paired with valid CSS sizes (e.g., rem
, px
). This approach narrowed string types to enforce specific formats, preventing errors like invalid CSS values at compile time.
Leveraging Conditional Types and Never for Safety
Christian delved into conditional types and the never
type to enhance compile-time safety. He introduced a NoEmptyString
type that prevents empty strings from being assigned, using a conditional check to return never
for invalid inputs. Applying this to a failOnEmptyString
function ensured that only non-empty strings were accepted, catching errors before runtime. He also demonstrated exhaustive switch cases, using never
to enforce complete coverage. For a getCountryForLocation
function, assigning an unhandled London
case to a never
-typed variable triggered a compile-time error, ensuring all cases were addressed.
Unraveling Types with Infer and Recursion
The infer
keyword was a highlight, enabling Christian to extract type information dynamically. He created a custom MyReturnType
to mimic TypeScript’s ReturnType
, inferring a function’s return type (e.g., number
for an addition function). This was particularly useful for complex type manipulations. Recursion was showcased through an UnnestArray
type, unwrapping deeply nested arrays to access their inner types (e.g., extracting string
from string[][][]
). He also built a recursive Tuple
type, generating fixed-length arrays with specified element types, such as a three-element RGB tuple, with an accumulator to collect elements during recursion.
Branded Types for Enhanced Type Safety
Christian concluded with branded types, a technique to distinguish specific string formats, like emails, without runtime overhead. By defining an Email
type as a string intersected with an object containing a _brand
property, he ensured that only validated strings could be assigned. A type guard function, isValidEmail
, checked for an @
symbol, allowing safe usage in functions like sendEmail
. This approach maintained the simplicity of primitive types while enforcing strict validation, applicable to formats like UUIDs or custom date strings.