Тип ответа функции на основе входной строки

#typescript

#машинописный текст #typescript

Вопрос:

Я пытаюсь написать клиент для API Bitcoin json-rpc и хочу получить надежные гарантии типа. Однако, похоже, я не могу найти простой способ определить тип ответа call функции на основе ввода параметра cmd.

Приведенный ниже код работает (вы можете изменить последнюю строку на call("getnewaddress").amount , и это приведет к ошибке, но он кажется подробным. Есть ли более программный способ сделать это?

 interface RPCResponse {
  getbalance: {
      amount: number
  };
  getnewaddress: {
      address: string
  };
}

type RPCCommand = keyof RPCResponse;

type RPCResponses<T> = 
    T extends "getbalance" ? RPCResponse["getbalance"] :
    T extends "getnewaddress" ? RPCResponse["getnewaddress"] :
    never;

function call<T extends RPCCommand>(cmd: T): RPCResponses<T> {
    
    if (cmd === "getbalance")
        return { amount: 1 } as RPCResponses<T>;

    if (cmd === "getnewaddress")
        return {address: "test"} as RPCResponses<T>;

  throw new Error("never");
}

console.log(call("getnewaddress").address)
  

Ответ №1:

В TypeScript вы можете иметь несколько подписей для функции, используя перегрузку функции.

Этот код относительно прост, обеспечивая при этом надежные гарантии типа.

 interface RPCResponseBalance {
    amount: number;
}

interface RPCResponseAddress {
    address: string;
}


function call(cmd: 'getbalance'): RPCResponseBalance;
function call(cmd: 'getnewaddress'): RPCResponseAddress;
function call(cmd: unknown) {
    if (cmd === "getbalance")
        return { amount: 1 }

    if (cmd === "getnewaddress")
        return { address: "test" }

    throw new Error("never");
}

console.log(call("getnewaddress").address)
  

Игровая площадка