Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using conditional return type depending on boolean parameter

Tags:

typescript

I am writing a library and I'd like to provide more accurate Types, so that library users can't choose the wrong type in my below example.

This method either returns IPlayerStats or IStatsItem[] if the parameter convertJSONOutput is set to true.

public async getStatsById(
    userId: string,
    timeWindow: TimeWindow = TimeWindow.Alltime,
    convertJSONOutput: boolean = true
  ): Promise<IPlayerStats | IStatsItem[]> {
  // Ommitted
}

The question:

Can I specify a conditional return type which indicates what interface will be returned (depending on the convertJSONOutput boolean parameter)?

like image 767
kentor Avatar asked Sep 15 '25 22:09

kentor


1 Answers

The simplest way to return different types based on a boolean argument would be overloads:

function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: true): Promise<IPlayerStats>;
function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: false): Promise<IStatsItem[]>;
function getStatsById(
    userId: string,
    timeWindow: TimeWindow = TimeWindow.Alltime,
    convertJSONOutput: boolean = true
  ): Promise<IPlayerStats | IStatsItem[]> {

When you call it, the narrowed type is then inferred based on the value of the argument:

// Promise<IPlayerStats>
const a = getStatsById('', undefined, true);

// Promise<IStatsItem[]>
const b = getStatsById('', undefined, false);

The important part is that each overload specifies the exact literal value true or false, rather than the type boolean. The return type is then tied to this. I've highlighted the relationship below.

//                              **** =>        ************
getStatsById(convertJSONOutput: true): Promise<IPlayerStats>;

I have slightly adapted the code so I could create a stand-alone example, it assumes TimeWindow, IStatsItem, and IPlayerStats are already defined:

function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: true): Promise<IPlayerStats>;
function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: false): Promise<IStatsItem[]>;
function getStatsById(
    userId: string,
    timeWindow: TimeWindow = TimeWindow.Alltime,
    convertJSONOutput: boolean = true
  ): Promise<IPlayerStats | IStatsItem[]> {
  // Ommitted
}

// Promise<IPlayerStats>
const a = getStatsById('', undefined, true);

// Promise<IStatsItem[]>
const b = getStatsById('', undefined, false);
like image 128
Fenton Avatar answered Sep 19 '25 15:09

Fenton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!