Maximizing Code Safety and Flexibility: Power of TypeScript Generics and Partials

Mahesh Guntumadugu
3 min readJul 29, 2023
Photo by Paulius Andriekus on Unsplash

When working on a project that includes both JavaScript and TypeScript code, you can leverage the benefits of TypeScript features like Generics and Partials in certain parts of the codebase while keeping the existing JavaScript code untouched. TypeScript allows for seamless integration, making it easy to adopt new features incrementally.

  1. Combining JavaScript and TypeScript: Suppose you have an existing JavaScript function that finds the minimum value in an array:
function findMin(arr) {
return Math.min(...arr);
}

const numbers = [5, 3, 8, 1, 4];
const minimum = findMin(numbers); // Result: 1

Here, we have a basic JavaScript function that works fine. But now, let’s introduce TypeScript to enhance type safety and code clarity.

2. Using TypeScript Generics: With TypeScript, we can add Generics to make the function more robust and reusable:

function findMin<T extends number>(arr: T[]): T {
return Math.min(...arr);
}

const numbers = [5, 3, 8, 1, 4];
const minimum = findMin(numbers); // Result: 1 (inferred type: number)

By using a generic type T extends number, we enforce that the array must contain elements of numeric types only. This prevents accidentally passing arrays with non-numeric elements, providing better type checking and avoiding runtime errors.

3. Utilizing TypeScript Partials:

Let’s consider a scenario where you want to introduce a configuration object to customize the behavior of your existing JavaScript function:

function processArray(arr, config) {
// Some processing logic based on the config
return arr.map(item => item * config.multiplier);
}

const numbers = [1, 2, 3, 4, 5];
const config = { multiplier: 2 };
const processedArray = processArray(numbers, config); // Result: [2, 4, 6, 8, 10]

Now, you want to make the config object's properties optional and provide default values using TypeScript Partials.

4. Leveraging TypeScript Partials:

type Config = Partial<{ multiplier: number }>;

function processArray(arr: number[], config: Config = {}): number[] {
const { multiplier = 1 } = config;
return arr.map(item => item * multiplier);
}

const numbers = [1, 2, 3, 4, 5];
const config = { multiplier: 2 };
const processedArray = processArray(numbers, config); // Result: [2, 4, 6, 8, 10]

By defining a Config type as Partial<{ multiplier: number }>, we make the multiplier property optional, and if not provided, it defaults to 1. This enhances the flexibility and maintainability of the code while keeping backward compatibility with the existing JavaScript function.

Finally, a few Advantages of TypeScript with Generics and Partials:

  1. Type Safety and Error Prevention: Using Generics and Partials in TypeScript enables catching type-related errors early during the development phase. This leads to more reliable code and helps prevent bugs in production.
  2. Code Reusability: Generics allow you to create flexible and reusable functions that work with various data types, enhancing code modularity and maintainability.
  3. Easy Migration: By incrementally introducing TypeScript features like Generics and Partials, you can gradually migrate your existing JavaScript codebase to TypeScript without rewriting everything from scratch.
  4. Improved Collaboration: TypeScript’s static typing and clear type definitions make it easier for teams to understand and collaborate on the codebase, leading to more consistent and predictable development.

--

--

Mahesh Guntumadugu

I'm not just a Senior Engineer— My belief? The world is a better place when we lift each other up. 😃. https://www.curiousengineers.in