Typescript推断的对象文字类型加宽是如何工作的?

Typescript推断的对象文字类型加宽是如何工作的?,typescript,Typescript,我读过typescript是如何变宽的,但仍然不确定发生了什么: type Def={ 'T':{状态:5,数据:{r:'m'}}, } 功能路线 (路由:S,处理程序:()=>Promise){} 路由('T',异步函数(){ 返回{状态:5,数据:{r:'m'}; }); 这在Typescript中工作正常,但不应引发错误,因为Typescript将route()的第二个参数的类型推断为()=>{状态:编号,数据:{r:string} 我问你是因为我对你有意见。传递到Router::get

我读过typescript是如何变宽的,但仍然不确定发生了什么:

type Def={
'T':{状态:5,数据:{r:'m'}},
}
功能路线
(路由:S,处理程序:()=>Promise){}
路由('T',异步函数(){
返回{状态:5,数据:{r:'m'};
});
这在Typescript中工作正常,但不应引发错误,因为Typescript将
route()
的第二个参数的类型推断为
()=>{状态:编号,数据:{r:string}


我问你是因为我对你有意见。传递到
Router::get
的函数被推断为
()=>{status:number}
,而不是
()=>{status:200}
。奇怪的是,当我删除
POST
route()时,没有出现任何错误。

这个简单的示例确实按预期工作,并且这里没有发生文字类型加宽-函数
route()
是泛型的,而
S
是首先推断的,因为您调用它时没有指定其泛型类型参数
S

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

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

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

我不知道为什么这样做不起作用,但我怀疑
ApiDefBase
中的索引签名会阻止类型推断对
Path
的影响-如果在简单示例中添加类似的索引签名,则会出现相同的错误:

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'.
type DefBase={[p在字符串中]:{}
接口Def扩展了DefBase{
'T':{状态:5,数据:{r:'m'}},
}
功能路线
(路由:S,处理程序:()=>Promise){}
路由('T',异步函数(){
返回{状态:5,数据:{r:'m'};
});
“()=>Promise”类型的参数不能分配给“()=>Promise”类型的参数。
类型“Promise”不可分配给类型“Promise”。
类型“{status:number;数据:{r:string;};}”不能分配给类型“{status:5;数据:{r:m;};}”。
属性“状态”的类型不兼容。
类型“number”不可分配给类型“5”。
现在,为什么添加索引签名会对类型推断产生这种影响?我不知道

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'.