Как вывести тип возврата Promise на основе аргументов функции? - PullRequest
3 голосов
/ 21 февраля 2020
type Actions =
  | ['add', number, number] // should return number
  | ['log', string]; // should return void


type Call = (...args: Actions) => Promise<?>;

const call: Call = (...args: Actions): Promise<?> => {
  // returns some Promise
}

call('add', 1, 1).then(value => {
   // value is then inferred as number
})


call('log', 'Hello World!').then(value => {
   // value is then inferred as void
})

Как вы основываете возвращаемое значение Обещания из любых аргументов, переданных функции?

1 Ответ

5 голосов
/ 21 февраля 2020

Два подхода для вас:

  1. С вашим типом Call в качестве типа перегруженной функции
  2. С просто перегруженной функцией.

С вашим Call типом

Тип, который вы хотите для Call, является перегруженным типом функции. Вы можете определить это так:

type Call = {
    (...args: ['add', number, number]): Promise<number>;
    (...args: ['log', string]): Promise<void>;
};

Поскольку вам необходимо связать тип возвращаемого значения со списком параметров, тип Actions на самом деле не помогает.

Функция, набранная с помощью этот тип будет делать вывод, который вы просили:

function doSomething(fn: Call) {
    fn('add', 1, 2)
        .then(value => {
            // Here, TypeScript infers `value` is of type `number`
        });
    fn('log', 'message')
        .then(value => {
            // Here, TypeScript infers `avlue` is of type `void`
        });
}

На игровой площадке

Если вы собираетесь писать для этого функции, это может помочь иметь несколько типов помощников:

type AddParams = ['add', number, number];
type LogParams = ['log', string];
type ActionParams =
    | AddParams
    | LogParams;

type Call = {
    (...args: AddParams): Promise<number>;
    (...args: LogParams): Promise<void>;
};

Затем, например:

const call: Call = (...args: ActionParams): Promise<any> => {
    // (Dummy implementation)
    if (args[0] === 'add') {
        return Promise.resolve(args[1] + args[2]);
    }
    return Promise.resolve();
};

На детской площадке

С просто перегруженной функцией

Если вы просто хотите написать перегруженную функцию, вам не нужен тип Call (вы, вероятно, знаете это):

type AddAction = ['add', number, number];
type LogAction = ['log', string];
type Actions =
    | AddAction
    | LogAction;

function call(...args: AddAction): Promise<number>;
function call(...args: LogAction): Promise<void>;
function call(...args: Actions): Promise<any> {
    // ...implementation...
}

call('add', 1, 2)
    .then(value => {
        // Here, TypeScript infers `value` is of type `number`
    });
call('log', 'message')
    .then(value => {
        // Here, TypeScript infers `avlue` is of type `void`
    });

На игровой площадке

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