我读过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()
?我问是因为我对this code有意见。传递到
() => {status: number, data: {r: string}}
的函数被推断为Router::get
而不是() => {status: number}
。奇怪的是,当我删除() => {status: 200}
路由(shown here)时没有出现错误。 最佳答案
这个简单的例子并不像预期的那样工作,文字类型加宽在这里不发生——函数route()
是通用的,并且首先推断“cc>”,因为您在不指定其泛型类型参数“cc>”的情况下调用它。
route('T', async function () {
return { status: 5, data: {r: 'm'} };
});
因此,首先,编译器必须从传递的实际参数类型中推断出
S
。通过查看第一个参数,文字
S
,它确定S
为文字类型'T'
。因此,立即返回类型的第二个参数,
S
变得固定为定义为'T'
的对象文字类型。然后,编译器不需要推断异步函数的返回类型,它只需检查它是否符合() => Promise<Def[S]>
(即符合)。为什么这不起作用?AA>我不知道,但是我怀疑在
Def['T']
中的索引签名阻止了类型推断对Def['T']
的影响。如果你把相似的索引签名添加到这个简单的例子中,你会得到同样的错误:type DefBase = { [p in string]: {}}
interface Def extends DefBase {
'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'} };
});
Argument of type '() => Promise<{ status: number; data: { r: string; }; }>' is not assignable to parameter of type '() => Promise<{ status: 5; data: { r: "m"; }; }>'.
Type 'Promise<{ status: number; data: { r: string; }; }>' is not assignable to type 'Promise<{ status: 5; data: { r: "m"; }; }>'.
Type '{ status: number; data: { r: string; }; }' is not assignable to type '{ status: 5; data: { r: "m"; }; }'.
Types of property 'status' are incompatible.
Type 'number' is not assignable to type '5'.
现在,为什么添加索引签名会对类型推断产生这种影响-我不知道。