1
\$\begingroup\$

I need to take a user's name and format it 'lastName, firstName middleName'. If firstName and middleName are not present then the comma should not be included with lastName. Below is what I came up with and I'm wondering if there are ways I can make this better.

The code was adapted from another function written by a senior developer at my company. I'm trying to expand my way of problem-solving for conditional situations.

export function getLastNameFirstNameFullUserName(
  user: { firstName?: string; lastName?: string; middleName?: string },
  includeMiddleName = false,
): string {
  const { firstName, lastName, middleName } = user;

  const userNameArray: string[] = [];

  if (isNotEmptyString(lastName)) {
    useLastNameWithComma(firstName, includeMiddleName, middleName)
      ? userNameArray.push(`${lastName},`)
      : userNameArray.push(`${lastName}`);
  }

  isNotEmptyString(firstName) && userNameArray.push(`${firstName}`);

  includeMiddleName && isNotEmptyString(middleName) && userNameArray.push(`${middleName}`);

  return userNameArray.join(' ');
}

function useLastNameWithComma(firstName: string, includeMiddleName: boolean, middleName?: string): boolean {
  if (isNotEmptyString(firstName)) {
    return true;
  }

  if (includeMiddleName && isNotEmptyString(middleName)) {
    return true;
  }

  return false;
}

export function isNotEmptyString(item: string | null | undefined): boolean {
  return !['', null, undefined].includes(item);
}
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Here are some ideas to consider:

  • Write "if" statements as normal if statements, ie. if (isNotEmptyString(first)) instead of isNotEmptyString(first) &&
  • Instead of the isNotEmptyString function, consider using the normal "truthy" value of strings. You can then more concisely write if (first) userNameArray.push(first). You may need to write it as !!first or Boolean(first) for typescript. Also, I'm not a fan of using "not" in function names, as it can easily lead to double negatives.
  • Remove unneeded string interpolation, like ${firstName}, which is just firstName.

Some more stylistic ideas:

  • Remove the word "Name" within variable names throughout. It makes the code bulkier with little benefit. I'd probably shorten the other variables too, without obfuscating anything. With less bulk, things are often easier to parse through.
  • Rely on the result of evaluations to give you boolean values, instead of explicitly returning the constants true or false. For example, you can write useLastNameWithComma as:
function useLastNameWithComma(firstName: string, 
                              includeMiddleName: boolean, 
                              middleName?: string): boolean {
  return !!firstName || (includeMiddleName && !!middleName)
}

To me, this is easier to understand the logic when it's in one line, but not everyone would agree.

  • Consider scoping useLastNameWithComma into the function you're writing, and then you don't have to pass all the variables and there's not as much to follow. It will just encapsulate the logic in a nice, named place.

Hope this helps!

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for your feedback! * I agree with the if statements rather than boolean &&. This was something adapted from my senior's code but is a weird style choice. * isNotEmptyString was also a utility he made as he prefers very declarative approaches. I'm more partial to the normal truthy way you describe. * String interpolation was needed because the compiler wasn't eliminating the undefined type, but with your method this is unneeded. * Using "name" is required here because it's used in other places in the system. This matches our system design but I see your point \$\endgroup\$
    – Samuel
    Jan 5 at 0:00
1
\$\begingroup\$

This was the solution I ended up using with the help of a coworker and the answer above.

  • Using if-statements with normal truthy checks removes the need to cast the optional parameters to string.
  • Adding the last name at the end allowed me to remove the helper function that determines if a comma needs to be added.
    • Instead, we can just check that the array has an item already (first or middle name pushed) to know if we need to include the comma with the last name.
    • Then we can use unshift to add it to the front of the array.

I think this is a marked improvement in readability and reducing lines compared to the first version.

export function getLastNameFirstNameFullUserName(
  user: { firstName?: string; lastName?: string; middleName?: string },
  includeMiddleName = false,
): string {
  const { firstName, lastName, middleName } = user;

  const userNameArray: string[] = [];

  if (firstName) { 
    userNameArray.push(firstName); 
  }

  if (includeMiddleName && middleName) { 
    userNameArray.push(middleName); 
  }

  if (lastName) {
    const formattedLastName: string = userNameArray.length > 0 ? `${lastName},` : lastName;

    userNameArray.unshift(formattedLastName);
  }

  return userNameArray.join(' ');
}
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.