skip to Main Content

I heard that declaring optional types is bad in typescript.
In my app, there’s two functions that needs to call createPayment.
createPayment takes a payment payload which is of type Payment

On the first function (onCreatePayment), firstName, lastName and contactNumber shouldn’t be pass while on the second function (onCreateAnotherPayment), it needs to be pass. If I don’t pass firstName, lastName and contactNumber in the 1st function, it complains because I’ve declare it as not optional in type.

What is the correct approach to this?

1st function

const onCreatePayment = () => {
  ...
  try {
    const { data } = await createPayment(
      {
        payment_link_id,
        payment_method_provider,
        payment_method_method,
        custom_amount,
        customer_details: {
          noteToMerchant: notes,
        },
      },
    );

    return ...
  } catch (error) {
    ...
  }
};

2nd function

const onCreateAnotherPayment = () => {
  ...
  try {
    const { data } = await createPayment(
      {
        payment_link_id,
        payment_method_provider,
        payment_method_method,
        custom_amount,
        customer_details: {
          noteToMerchant: notes,
          firstName,
          lastName,
          contactNumber,
    },
      },
    );

    return ...
  } catch (error) {
    ...
  }
};

API

export const createPayment = (data: Payment, config?: ApiRequestConfig) => {
  return api.post<PaymentResponse>(
    `/payments`,
    data,
    config,
  );
};

Type

export type Payment = {
  payment_link_id: string;
  payment_method_provider: string;
  payment_method_method: string;
  custom_amount: number;
  customer_details: {
    noteToMerchant: string;
    firstName: string;
    lastName: string;
    contactNumber: string;
  };
};

2

Answers


  1. There are no hard rules on whether to avoid optional or not, so as long as it satisfies your requirement, you are good to go.

    In the book Clean Code, the only time it mentioned about to avoid using optional is when passing an argument into a function unless it’s the very last argument for the function. And if there’s more than one optional properties needs to be passed into the argument of the function, consolidate them into an object and pass that single object as the last argument.

    So to recap, there’s really no hard requirement to avoid an optional types as long as it fits your needs.

    However, if you really want to avoid the optional types, my personal preference is to do what Redux does — introduce the initial state/data. So in the same file of your createPayment function, create an initial data for your data like so —

    const initialCreatePaymentPayload = {
      payment_link_id: '',
      payment_method_provider: '',
      payment_method_method: '',
      custom_amount: '',
      customer_details: {
        noteToMerchant: '',
        firstName: '',
        lastName: '',
        contactNumber: '',
      };
    }
    

    Then in your createPaymen function, apply the following —

    export const createPayment = (data: Payment, config?: ApiRequestConfig) => {
      const requestPayload = {
        ...initialCreatePaymentPayload,
        ...data,
      }
      return api.post<PaymentResponse>(
        `/payments`,
        requestPayload,
        config,
      );
    };
    

    Now you won’t have to worry about declaring optional types.

    Again, I want to emphasis that avoiding optional types is pointless as long as it fits your needs, and there are absolutely no hard rules in the Typescript world that you should do so.

    Login or Signup to reply.
  2. Like other answers/comments suggested, having optional properties is not really a bad practice.

    But if you are looking to avoid doing that, you can use the Omit utility to create a new type when you need to omit some of the properties you do not need, or use the Pick utility to create a new type for picking just the properties you need.

    Referencing: Typescript Utility Types

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search