Я пишу библиотеку и хотел бы предоставить более точные типы, чтобы пользователи библиотеки не могли выбрать неправильный тип в моем примере ниже.

Этот метод либо возвращает IPlayerStats, либо IStatsItem[], если для параметра convertJSONOutput установлено значение true.

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

Вопрос:

Могу ли я указать тип условного возврата, который указывает, какой интерфейс будет возвращен (в зависимости от логического параметра convertJSONOutput)?

3
kentor 14 Окт 2018 в 13:01

1 ответ

Лучший ответ

Самый простой способ вернуть разные типы на основе логического аргумента - это перегрузки:

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[]> {

Когда вы его вызываете, суженный тип выводится на основе значения аргумента:

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

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

Важная часть состоит в том, что каждая перегрузка указывает точное буквальное значение true или false, а не тип boolean. Затем к нему привязывается возвращаемый тип. Я выделил отношения ниже.

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

Я немного адаптировал код, чтобы создать автономный пример, он предполагает, что TimeWindow, IStatsItem и IPlayerStats уже определены:

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);
5
Fenton 2 Май 2019 в 14:29