Mastering Declaration Merging in TypeScript
Declaration merging is a powerful feature in TypeScript that allows you to combine multiple declarations of the same name into a single definition. This is particularly useful for extending existing types, adding properties to built-in JavaScript objects, or integrating with third-party libraries. This challenge will test your understanding of how to effectively use declaration merging to enhance type safety and code organization.
Problem Description
Your task is to implement declaration merging in TypeScript in two distinct scenarios:
- Extending Built-in JavaScript Objects: You need to add a new method to the
Stringprototype, making it accessible on all string instances. - Augmenting Third-Party Library Interfaces: You will simulate augmenting an interface from a hypothetical third-party library to add new properties.
You should demonstrate your ability to:
- Declare new members (methods, properties) for existing JavaScript global objects.
- Augment existing interfaces by adding new properties.
- Ensure that the merged declarations are correctly typed and usable.
Key Requirements:
- String Extension: Implement a method named
reverseStringonString.prototypethat returns a reversed version of the string it's called on. - Interface Augmentation: Create an interface named
UserConfig(assume it's defined elsewhere in a library) and then augment it to add a new optional property calledthemeColorof typestring. - Demonstrate Usage: Provide clear examples showing how to use both the extended string method and the augmented interface.
Expected Behavior:
- Calling
.reverseString()on any string literal or string variable should return the reversed string. - Instances of a type that implements
UserConfigshould be able to optionally include athemeColorproperty.
Examples
Example 1: String Extension
// Assume this is how you'd use it
const originalString = "TypeScript";
const reversedString = originalString.reverseString();
console.log(reversedString); // Expected: "tpircSepyT"
Example 2: Interface Augmentation
// Assume UserConfig is imported from a library
// declare module 'my-config-library' {
// interface UserConfig {
// userId: number;
// // other properties...
// }
// }
interface UserConfig {
userId: number;
// other properties...
}
// Your augmentation here
const user1: UserConfig = {
userId: 123,
themeColor: "blue"
};
const user2: UserConfig = {
userId: 456
};
console.log(user1.themeColor); // Expected: "blue"
console.log(user2.themeColor); // Expected: undefined
Constraints
- Your solution must be written entirely in TypeScript.
- You should not modify the original JavaScript
Stringprototype or any hypothetical library code directly. Instead, use TypeScript's declaration merging features. - The
themeColorproperty forUserConfigshould be optional.
Notes
- To extend built-in JavaScript objects, you'll need to use a declaration file (
.d.ts) or declare the augmentation within a global scope. - For interface augmentation, ensure you're targeting the correct interface name.
- Think about how TypeScript's type system allows you to "see" and interact with these merged declarations.