如何为TypeScript中的函数映射到一组输出的一组输入定义类型?

时间:2019-07-11 21:59:14

标签: typescript

我想做以下事情:

enum Opts {
    One = 'one',
    Two = 'two',
    Three = 'three',
}

interface OneOpts {
    foo: string;
    bar: string;
}

interface TwoOpts {
    one: string;
    two: string;
}

interface ThreeOpts {
    a: string;
    b: string;
}

interface FunctionResponse<T> {
    id: string;
    href: string;
    options: T;
}

type StartArgs =
    | [Opts.One, OneOpts]
    | [Opts.Two, TwoOpts]
    | [Opts.Three, ThreeOpts]

type FunctionReturn = FunctionResponse<OneOpts | TwoOpts | ThreeOpts>

const start = async (...args: StartArgs): Promise<FunctionReturn> => {
    const [ first, second ] = args
    //...
    const results: FunctionReturn = await new Promise(() => {
        //...
    })

    return results
}

// Current:
start(Opts.One, { foo: 'string', bar: 'another' })
.then((result: TwoOpts) => { // passed :(
    //...
})

// Desired result:
start(Opts.One, { foo: 'string', bar: 'another' })
.then((result: TwoOpts) => { // ERROR
    //...
})

具体来说,我想根据发送给它的一组输入args推断函数的返回类型。在TypeScript中执行此操作的好方法是什么?

我能够通过StartArgs类型使输入args正确关联。但是,如果我尝试通过以下方式对整个功能执行此操作:

type myFunc = 
    | (args: [type, type2]): type3
    | (args: [type, type2]): type3
    | (args: [type, type2]): type3

在这种情况下,编译器抱怨...args自动转换为any[]

Playground Example

1 个答案:

答案 0 :(得分:1)

您可以为此使用函数重载:

interface OneOpts {
  foo: string;
  bar: string;
}

interface TwoOpts {
  one: string;
  two: string;
}

interface ThreeOpts {
  a: string;
  b: string;
}

interface FunctionResponse<T> {
  id: string;
  href: string;
  options: T;
}

function start(opts: OneOpts): Promise<FunctionResponse<OneOpts>>;
function start(opts: TwoOpts): Promise<FunctionResponse<TwoOpts>>;
function start(opts: ThreeOpts): Promise<FunctionResponse<ThreeOpts>>;
function start(opts: OneOpts | TwoOpts | ThreeOpts) {
  return Promise.resolve({
    id: "xyz",
    href: "url",
    options: opts
  });
}

start({ foo: "foostring", bar: "barstring" }).then(
  (result: FunctionResponse<OneOpts>) => console.log(result)
);

Playground Link