Module lessons (2/2)
Literal Types and Assertions
TypeScript provides advanced tools to narrow down the possible values of variables and to force the compiler to recognize more specific types when necessary.
Literal Types
A literal type represents an exact, single value (for example, a specific string or number). They are usually combined with union types:
type TrafficLight = 'red' | 'yellow' | 'green';
let light: TrafficLight;
light = 'red'; // OK
light = 'blue'; // Error: "blue" is not assignable to TrafficLightType Assertions (as)
Sometimes you have information about a type that TypeScript cannot know at compile time. In these cases, you can use a type assertion using the as keyword:
const myCanvas = document.getElementById('main_canvas') as HTMLCanvasElement;The assertion tells the compiler: "Trust me, I know this element is an HTMLCanvasElement". It does not perform any checks or casts at runtime; it only helps the type checker.
Const Assertions (as const)
When we declare an object or an array with const, TypeScript still allows modifying its internal properties. By adding as const at the end, the entire structure is frozen and made read-only, converting all properties into their exact literal types:
const colors = ['red', 'green', 'blue'] as const;
// colors[0] = "yellow"; // Error: array is read-onlyTemplate Literal Types
Template literal types are built on top of JavaScript template strings, but are used in type positions. They allow combining multiple literal types into one:
type Size = 'small' | 'large';
type Color = 'red' | 'blue';
// Creates the union: "small-red" | "small-blue" | "large-red" | "large-blue"
type ItemId = `${Size}-${Color}`;String Utilities in Template Literal Types
TypeScript provides special utility types to manipulate characters within Template Literal Types:
Capitalize<StringType>: Capitalizes the first letter of the string.Uncapitalize<StringType>: Uncapitalizes the first letter of the string.Uppercase<StringType>: Converts the entire string to uppercase.Lowercase<StringType>: Converts the entire string to lowercase.
type ActionType = 'click' | 'hover';
// Generates: "onClick" | "onHover"
type EventHandlers = `on${Capitalize<ActionType>}`;Try it yourself
Exercise 1: Direction Literal Union
Define a literal type named Direction that accepts only the strings 'up', 'down', 'left', or 'right'. Then declare a function named move(dir: Direction): string that returns the string 'Moving ' followed by the received direction.
Show hint
Define the type alias first with the four options separated by |, then declare the move function annotating the parameter and the return type.
Solution available after 3 attempts
Exercise 2: Assertion on JSON.parse
The JSON.parse function returns the any type by default. Modify the parseUser function so that the result of JSON.parse(json) is asserted as type { username: string } using the as keyword.
Show hint
Add 'as { username: string }' immediately after the JSON.parse(json) call.
Solution available after 3 attempts
Exercise 3: Template Literal for Events
Given the Status and Action types, define a template string type named Event in the format 'Status-Action' (for example, 'open-click').
Show hint
Use backticks to define the type, and the ${Status}-${Action} syntax inside.
Solution available after 3 attempts
Exercise 4: Template Literal Type with Capitalize
Define a literal type Event that can be 'click' or 'hover'. Then, use Template Literal Types to declare a type EventHandler representing strings in the format on followed by the capitalized event name (i.e., 'onClick' or 'onHover').
Show hint
Use Capitalize<Event> inside the template literal to capitalize the first letter of the event.
Solution available after 3 attempts