Home > Back-end >  How to transform the selected options from a form into a payload object without the need of the bang
How to transform the selected options from a form into a payload object without the need of the bang

Time:12-22

I have a form input developed in React that have several fields and a "Send" button. The button should only be enabled when all the required fields are filled. After pressing "Send", I want to transform the inputted information into a new payload so I can send it to my backend.

The problem is, the input properties could be null if the user hasn't inputted anything yet. But when I hit "Send", I'm sure that these properties are not null anymore, as the button is only enabled when the inputs are filled. But when transforming my selected options into my payload I don't see a way of not using the bang operator, as Typescript is not aware that I have already validated the required inputs.

Here is a simplified example of the code.

interface SelectedOptions {
  userInfo: {
    name: string | null;
    age: number | null
  };
  address: string | null;
}

interface Payload {
  name: string;
  age: number;
  address: string | null;
}

const validateOptions = (options: SelectedOptions) => {
  return options.name && options.age;
}

const transformOptionsIntoPayload = (options: SelectedOptions) => {
  // If this method is being called, I'm sure that "options" have all the required fields filled.
  const payload: Payload = {
    name: options.userInfo.name!, // Bang operator
    age: options.userInfo.age!, // Bang operator
    address: options.address
  }
  return payload;
}

Is there a better way to handle this situation? Or should I just ignore es-lint's warning about the bang operator?

CodePudding user response:

You can use a type guard to let the TS compiler know that the supplied input conforms with your desired type.

const validateOptions = (options: SelectedOptions):options is Payload => !!(options.name && options.age)

Then in your code

if (validateOptions(formData)) {
  // formData inside your if will be treated as Payload
}

CodePudding user response:

Hi @Gustavo Cesário,

In my opinion, the non-null assertion operator is not my preferred choice. If given the option, I would rather use the optional chaining operator for the same purpose (?.) to safely access properties of an object that may be null or undefined. Like user?.name. That just things for that option. So, I just add that here.

Alternatively, I'm using Required<SelectedOptions> with as keyword.

const transformOptionsIntoPayload = (options: SelectedOptions) => {
  const payload: Payload = {
    name: options.userInfo.name,
    age: options.userInfo.age,
    address: options.address
  }
  return payload;
}

const options: SelectedOptions = {
  userInfo: { name: 'DSDmark', age: 60 },
  address: 'nar at 3.4'
};

if (validateOptions(options)) {
  const payload = transformOptionsIntoPayload(options as Required<SelectedOptions>);
}

TypeScript will treat the options object as if it has all the required fields filled on that way.

  • Related