DEV Community

TK
TK

Posted on • Originally published at leandrotk.github.io

3

Typescript Interesting Types

Soil

This post was originally published at TK's blog.

These days I'm building a new project to understand some topics deeply. It is about user experience, web performance, accessibility, and a type system for consistent data.

This project I'm basically using React with Typescript. At first, I implemented a custom hook to handle the data fetching. One of the possible data types the fetch could return is a Product type. It looks like this:

type Product = {
  name: string;
  price: number;
  imageUrl: string;
  description: string;
  isShippingFree: boolean;
  discount: number;
};
Enter fullscreen mode Exit fullscreen mode

Now that I could fetch some products, I wanted to use the list of products to render in the DOM. So I created a Product component. But as we are using Typescript, the props should be typed. In this case, I used the Product type. It looks like this:

export const Product = ({
  imageUrl,
  name,
  description,
  price,
  discount,
  isShippingFree,
}: ProductType) => (
  <Box>
    <Image imageUrl={imageUrl} imageAlt={name} />
    <TitleDescription name={name} description={description} />
    <Price price={price} discount={discount} />
    <Tag label="Free Shipping" isVisible={isShippingFree} />
  </Box>
);
Enter fullscreen mode Exit fullscreen mode

And when I started implementing the Image component, I just passed the imageUrl and the imageAlt as props. It looks like this:

export const Image = ({ imageUrl }) =>
  <img src={imageUrl} />;
Enter fullscreen mode Exit fullscreen mode

In this case, I couldn't use the Product type. But I could reuse it.

I learned about this new type: the Partial type. The idea of the Partial type is to build a new type based on the passed type and set all attributes to optional.

So, if we do a partial of the Product type, it would look like this:

type Product = {
  name?: string;
  price?: number;
  imageUrl?: string;
  description?: string;
  isShippingFree?: boolean;
  discount?: number;
};
Enter fullscreen mode Exit fullscreen mode

All properties are set to optional.

And now I can use it for the Image component:

export const Image = ({ imageUrl }): Partial<ProductType> =>
  <img src={imageUrl} />;
Enter fullscreen mode Exit fullscreen mode

But when I use the Image component, I can pass any props I want. I miss the type check. It doesn't break in compile time.

To fix that, I could just build an ImagePropsType and use it as the component props type.

type ImagePropsType = {
  imageUrl: string;
};

export const Image = ({ imageUrl }): ImagePropsType =>
  <img src={imageUrl} />;
Enter fullscreen mode Exit fullscreen mode

But I already have the type for the imageUrl inside the Product type. So I started to search how I could reuse the type: I found the Pick type.

The Pick type lets me reuse the Product type by picking a set of properties I want:

type ImagePropsType = Pick<ProductType, 'imageUrl'>;
Enter fullscreen mode Exit fullscreen mode

Now I ensure that type checking and the type reusability work well.

To build the whole Image component, I also needed to pass other props like: imageAlt and width.

What I wanted is the intersection of the Pick<ProductType, 'imageUrl'>, the imageAlt type, and the width type.

In Typescript, the representation of the intersection is the & operator.

I defined the ImageUrlType:

type ImageUrlType = Pick<ProductType, 'imageUrl'>;
Enter fullscreen mode Exit fullscreen mode

And the ImageAttrType to represent both the imageAlt and the width:

type ImageAttrType = { imageAlt: string; width?: string };
Enter fullscreen mode Exit fullscreen mode

And compose them together by insecting the types:

type ImagePropsType = ImageUrlType & ImageAttrType;
Enter fullscreen mode Exit fullscreen mode

And the final result is:

import { ProductType } from 'types/Product';

type ImageUrlType = Pick<ProductType, 'imageUrl'>;
type ImageAttrType = { imageAlt: string; width?: string };
type ImagePropsType = ImageUrlType & ImageAttrType;

export const Image = ({ imageUrl, imageAlt, width }: ImagePropsType) =>
  <img src={imageUrl} alt={imageAlt} width={width} />;
Enter fullscreen mode Exit fullscreen mode

I have the image URL, alt, width types intersected, and defined in the ImagePropsType. It can think of types as data and compose them. This is a very cool feature.

These are the interesting new types I learned this week.

My Twitter and Github.

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (2)

Collapse
 
jwp profile image
JWP

That is cool!

Collapse
 
teekay profile image
TK

Thanks! I'm glad you liked!

Retry later
👋 Kindness is contagious

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

Okay