Search code examples
typescriptoverloadingconditional-types

Function return type parameter dependent Typescript


I'm trying to make a function that converts a string to a boolean with an optional fallback in case the function wasn't successful. I have tried two simple approaches that I cannot wrap my head around on why it is not working.

Approach 1: Using a conditional type.

type toBooleanReturnType<T> =
T extends undefined
? boolean | undefined
: boolean | T

/**
 * Converts a string to a boolean
 * @param str
 * @param fallback the fallback value in case the string param is not 'true' nor 'false
 * @returns
 */
export const toBoolean = <T = undefined>(
  str: string,
  fallback?: T,
): toBooleanReturnType<T> => {
  if (str.trim() === 'true') return true;
  if (str.trim() === 'false') return false;
  if (fallback) return fallback;
  return undefined;
};

I get Type 'T' is not assignable to type 'toBooleanReturnType<T>' for the fallback return and Type 'undefined' is not assignable to type 'toBooleanReturnType<T>' for the undefined return.

Approach 2: Function overloading.

/**
 * Converts a string to a boolean
 * @param str
 * @param fallback the fallback value in case the string param is not 'true' nor 'false
 * @returns
 */
export function toBoolean<T>(
  str: string,
  fallback?: undefined,
): boolean | undefined
export function toBoolean<T>(
  str: string,
  fallback: T,
): boolean | T {
  if (str.trim() === 'true') return true;
  if (str.trim() === 'false') return false;
  if (fallback) return fallback as T;
  return undefined;
};

But I also get errors for the undefined return. Type 'undefined' is not assignable to type 'boolean | T'.

What is the proper way of doing this?


Solution

  • Oops, sorry. Solved this the second I posted the question.

    /**
     * Converts a string to a boolean
     * @param str
     * @param fallback the fallback value in case the string param is not 'true' nor 'false
     * @returns
     */
    export const toBoolean = <T = undefined>(
      str: string,
      fallback?: T,
    ): T | boolean => {
      if (str.trim() === 'true') return true;
      if (str.trim() === 'false') return false;
      return fallback as T;
    };