Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can I change the return type based on a parameter

I am unsure as to how to formulate my question, so bear with me if the question title looks incorrect to you.

function uselessFunction(value: number): string | number {
    if (value > 5) {
        return "false"
    }
    return 2
}

const uselessVar1 = uselessFunction(1);
// type is `string | number`
// expected would be `number`

const uselessVar2 = uselessFunction(10);
// type is `string | number`
// expected would be `string`.

I know about typeguard concept, and how I could use it, but that’s not my use-case.

function isString(value: string | number): value is string {
    if (typeof value === "string") {
        return true
    }
    return false
}

if (isString(uselessVar1) {
    // uselessVar1 type is `string`.
}

I would like to know if it’s possible for typescript to know if uselessVar1 is either a string or a number immediatly after the return, and how could I achieve this.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Also, as to the how is interesting to me, I’d also like to know if it’s a bad practice and why.

If you’re more interested in the original use-case…

/** 
 * Takes an input of type <T>[].
 * And returns bins of this list, of length binSize.
 * Example:
 *  
 * makeBinsFromArray([1, 2, 3, 4, 5], 3);
 * // [[1, 2, 3], [4, 5]]
 * 
 * makeBinsFromArray([1, 2, 3, 4, 5, 6, 7], 3);
 * // [[1, 2, 3], [4, 5, 6], [7]]
 * 
 * makeBinsFromArray([1, 2, 3, 4, 5, 6, 7], 3, true);
 * // [[1, 2, 3], [4, 5, 6], [7, undefined, undefined]]
*/
function makeBinsFromArray<T>(
  value: T[],
  binSize: number,
  fillLast?: boolean
): (T | (T | undefined))[][] {
  ...
}

const result = makeBinsFromArray([1, 2, 3], 2, true);
// expected type: (T | undefined)[][]

const result = makeBinsFromArray([1, 2, 3], 2);
// expected type: T[][];

Using this function, I want to know if I have a type T[][] or (T | undefined)[][] at compile time, depending on my fillLast argument.

>Solution :

Yes.

Function overloads are typically what you want here where you have different signature for each way that you want the function to be called.

function makeBinsFromArray<T>(
  value: T[],
  binSize: number,
  fillLast: true
): (T | undefined)[][]

function makeBinsFromArray<T>(
  value: T[],
  binSize: number,
  fillLast?: false
): T[][]

function makeBinsFromArray<T>(
  value: T[],
  binSize: number,
  fillLast?: boolean
): (T | (T | undefined))[][] {
  /// implementation
}

const resultA = makeBinsFromArray([1, 2, 3], 2, true);
// (T | undefined)[][]

const resultB = makeBinsFromArray([1, 2, 3], 2);
// T[][];

Playground


However, this isn’t going to work:

function uselessFunction(value: number): string | number {}
const uselessVar1 = uselessFunction(1); // `number`
const uselessVar2 = uselessFunction(10); // `string`.

You can can change the return based on the type of a parameter, but this performs logic based on a value. And a number type cannot be mathematically compared to another number type in Typescript, so this can’t work. string | number is the best you’ll get here.

Well, not impossible, but this path is not for the feint of heart. Nor, probably, a good idea.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading