Greetings, fellow developers! While we traverse the familiar landscapes of TypeScript, there exists an uncharted territory brimming with lesser-known gems that can infuse your code with power and elegance. In this journey, we'll delve into the depths of TypeScript's enigmatic toolkit, uncovering features that might have eluded your radar but hold the potential to transform your coding experience. So, fasten your seatbelts as we embark on an exhilarating expedition to discover these unsung heroes of TypeScript!
1. Mapped Types: Crafting Dynamic Transformations
Picture a toolkit that empowers you to craft dynamic transformations for your types. Welcome to the realm of Mapped Types! These versatile constructs allow you to wield the magic of type manipulation, breathing new life into your code.
type MagicMap<T> = { [K in keyof T]: T[K] | null };
const originalObj = { name: "Merlin", age: 1000 };
const nullableObj: MagicMap<typeof originalObj> = { name: "Gandalf", age: null };
Let's unravel the practical enchantment of mapped types:
type PartialAndNullable<T> = { [K in keyof T]?: T[K] | null };
interface User {
id: number;
name: string;
email: string;
}
const partialUser: PartialAndNullable<User> = { id: 1, name: null };
2. Conditional Types: Pioneering Type Predictions
Imagine gazing into a crystal ball that predicts and adapts types based on conditions. Say hello to Conditional Types! These mystical constructs enable you to weave intricate type logic, providing a dynamic edge to your code.
type IsString<T> = T extends string ? true : false;
type CheckString = IsString<"Wizard">; // true
Transcend into the realm of practical application:
type Pluck<T, K extends keyof T> = {
[P in K]: T[P];
};
interface Spell {
name: string;
incantation: string;
effect: string;
}
const spell: Pluck<Spell, "name" | "effect"> = {
name: "Levitation",
effect: "Objects float in the air",
};
3. Tuple Type: Symphony of Ordered Abstractions
Envision a symphony where data harmoniously follows an ordered arrangement. This is the magic of Tuple Types! These structured envoys bring a touch of elegance to your arrays, preserving both sequence and data types.
type SpellComponent = [string, number];
const fireball: SpellComponent = ["Fire", 3];
Harmonize your data with the power of tuples:
type Coordinate = [number, number];
function calculateDistance(pointA: Coordinate, pointB: Coordinate): number {
const [x1, y1] = pointA;
const [x2, y2] = pointB;
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}
4. Template Literal Types: Strings Amplified into Types
Imagine a realm where strings metamorphose into versatile types. Enter Template Literal Types, the enigmatic alchemy that binds strings and types in an intricate dance.
type Message<T> = `Hello, ${T}!`;
const greeting: Message<"Sorcerer"> = "Hello, mighty sorcerer!";
Unveil the practical magic within template literals:
type JoinStrings<T extends string, U extends string> = `${T} ${U}`;
type Combined = JoinStrings<"Enchanted", "Forest">; // "Enchanted Forest"
5. Infer Keyword: Unveiling the Cryptic Prophecies of Types
Enter the oracle's chamber, where types are unveiled through cryptic prophecies. The infer
keyword opens a portal to the hidden identities of types, adding an air of mystery to your code.
type InferReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function greet(): string {
return "Greetings!";
}
type Greeting = InferReturnType<typeof greet>; // string
Peer into the cryptic future with the power of type inference:
type Magic<T> = T extends infer U ? U extends string ? true : false : never;
type IsMagic = Magic<"abracadabra">; // true
6. Key Remapping in Mapped Types: Unleashing the Shapeshifting Powers
Visualize a world where keys within your types can be reshaped, remolded, and reborn anew. Key Remapping in Mapped Types offers you the power to unlock shapeshifting abilities for your data structures.
type RenameKey<T, K extends keyof T, NewKey extends string> = {
[P in keyof T as P extends K ? NewKey : P]: T[P];
};
interface Potion {
name: string;
duration: number;
}
type EnhancedPotion = RenameKey<Potion, "duration", "effectDuration">;
Unleash the transformative force of key remapping:
type Coordinate = { x: number; y: number };
type Offset = { dx: number; dy: number };
function translate(coord: Coordinate, offset: Offset): Coordinate {
return {
x: coord.x + offset.dx,
y: coord.y + offset.dy,
};
}
7. GlobalThis: Peering into the Global Horizon
Imagine gazing through a mystical window that grants you a view of the entire global realm. With GlobalThis
, you can access the cosmic nexus of global objects, uniting the various threads of your code's reality.
const globalVar = 42;
console.log(GlobalThis["globalVar"]); // 42
Harness the cosmic energy of GlobalThis
in your own code realms:
declare global {
interface Window {
mysticalScroll: string;
}
}
window.mysticalScroll = "Scroll of Ancient Wisdom";
Conclusion
Thanks for joining me on this little journey, we will see if there will be more parts to this series. If you have any questions or feedback, feel free to reach out to me ^^