Typescript推断对象文字类型扩展如何工作?

时间:2018-07-21 05:05:13

标签: typescript

我已经读过打字稿如何扩展inferred types,但仍不确定here的情况:

type Def = {
  'T': { status: 5, data: {r: 'm'}},
}

function route<S extends keyof Def>
   (route: S, handler: () => Promise<Def[S]>) { }

route('T', async function () {
   return { status: 5, data: {r: 'm'} };
});

这在Typescript游乐场中可以很好地工作,但是不应该引发错误,因为Typescript将route()的第二个参数的类型推断为() => {status: number, data: {r: string}}

我问,因为我遇到this code的问题。传递给Router::get的函数被推断为() => {status: number}而不是() => {status: 200}。奇怪的是,删除POST路由(shown here)时不会出现错误。

1 个答案:

答案 0 :(得分:1)

这个简单的示例确实按预期工作,并且此处不会发生字面量类型扩展-函数route()是泛型的,并且首先推断S是因为您在调用它时未指定其泛型类型参数{ {1}}:

S

因此,首先,编译器必须根据传递的实际参数的类型来推断route('T', async function () { return { status: 5, data: {r: 'm'} }; });

通过查看第一个参数文字S,它将确定'T'为文字类型S

因此,第二个参数'T'的返回类型立即固定为定义为() => Promise<Def[S]>的对象文字类型。然后,编译器无需推断异步函数的返回类型,只需检查其是否符合Def['T'](确实如此)。

为什么不起作用,in this, more complex code我不知道,但是我怀疑Def['T']中的索引签名会阻止类型推断对ApiDefBase的影响-如果您添加类似的索引签名到简单的示例,您将开始遇到相同的错误:

Path

现在,为什么添加索引签名会对类型推断产生这种影响-我不知道。