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