DEV Community

Bionic Julia
Bionic Julia

Posted on • Originally published at bionicjulia.com on

3 1

Override Part of an Existing Type in Typescript

I've recently been on a mission to eliminate all Typescript errors in our code base at work, and have been steadily chipping away at them systematically, during any downtime I get. I used to dislike Typescript when I first came across it, but really love it now and get an immense sense of satisfaction watching the red squigglies disappear as I work through each Typescript issue, bit by bit. 🤓

It was whilst doing this last week that I came across a situation that was new to me. What I was faced with was this...

I have a component that takes in a prop item which has an interface IItem defined as:

interface IItem extends PickerItemProps {
  iconSource?: ImageSourcePropType;
}

// ...and separately in another file, the React Native library provides this interface
export interface PickerItemProps {
  testID?: string;
  color?: ColorValue;
  label: string;
  value?: any;
}
Enter fullscreen mode Exit fullscreen mode

If you're not familiar with Typescript, extends effectively merges the PickerItemProps interface into IItem so that item can take this form, for example:

const item: IItem = { iconSource: 'imagesourcelocation', label: 'An item' }

// How it's used
;<ParentComponent item={item} />
Enter fullscreen mode Exit fullscreen mode

This issue I was faced with involved needing to extend the type label. Instead of it always being a plain string, I needed to allow label to also take the form of a component (the specific reason behind this has to do with how we're formatting certain bits of text in our app). Ideally then, label needs to either be of type string OR JSX.Element.

Because label actually belongs to and is defined in an external package, I didn't want to just change PickerItemProps directly (since these might unknowingly be overwritten on upgrades etc.). I therefore naively tried to do this, but quickly ran into Typescript complaining loudly.

interface IItem extends PickerItemProps {
  iconSource?: ImageSourcePropType;
  label: string | JSX.Element; // Typescript complains that label already exists
}

// No changes to this
export interface PickerItemProps {
  testID?: string;
  color?: ColorValue;
  label: string;
  value?: any;
}
Enter fullscreen mode Exit fullscreen mode

So what to do? The answer lies in using one of Typescript's utility types Omit. From the Typescript documentation, Omit<Type, Keys>...

Constructs a type by picking all properties from Type and then removing Keys (string literal or union of string literals).

What I could do in my case therefore, was to extends PickerItemProps without label, before then defining label as part of IItem like so:

interface IItem extends Omit<PickerItemProps, 'label'> {
  iconSource?: ImageSourcePropType;
  label: string | JSX.Element;
}

// Original definition remains untouched
export interface PickerItemProps {
  testID?: string;
  color?: ColorValue;
  label: string;
  value?: any;
}
Enter fullscreen mode Exit fullscreen mode

Questions or comments? Find my at my website, Twitter or Instagram.

Sentry mobile image

Mobile Vitals: A first step to Faster Apps

Slow startup times, UI hangs, and frozen frames frustrate users—but they’re also fixable. Mobile Vitals help you measure and understand these performance issues so you can optimize your app’s speed and responsiveness. Learn how to use them to reduce friction and improve user experience.

Read the guide →

Top comments (0)

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay