typescript - Typescript 推断的对象字面量类型扩展如何工作?
问题描述
我已经阅读了关于 typescript 如何扩大推断类型的信息,但我仍然不确定这里发生了什么:
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}}
?
我问是因为我对这段代码有疑问。传入的函数Router::get
被推断为() => {status: number}
而不是() => {status: 200}
. 奇怪的是,当我删除POST
路线时没有引发错误(显示在这里)。
解决方案
这个简单的示例确实按预期工作,并且此处不会发生文字类型扩展 - 函数route()
是通用的,并且S
首先被推断,因为您在没有指定其通用类型参数的情况下调用它S
:
route('T', async function () {
return { status: 5, data: {r: 'm'} };
});
所以,首先,编译器必须S
从传递的实际参数的类型中推断出来。
通过查看第一个参数 literal 'T'
,它确定S
为 literal type 'T'
。
因此,第二个参数的返回类型立即() => Promise<Def[S]>
固定为定义为的对象字面量类型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'.
现在,为什么添加索引签名会对类型推断产生这种影响——我不知道。
推荐阅读
- vue.js - 在 api 调用中使用变量时出现 CORS 错误
- python - pythonanywhere 上使用 Telethon 的 Telegram 客户端
- html - 带有溢出的相对父级的粘性标题
- javascript - 在javascript中拆分点或逗号
- javascript - 如何从文本中删除空格、标点和符号
- python - JIRA-Python 的基本身份验证不再适用于 REST API 调用。接下来是什么?
- java - 如何在 for 循环(数组)中的 if 语句中打印
- android - 使用 AndroidX 概述的 TextField
- java - 测试:MySQL和H2不兼容
- ios - 在 NativeScript 5.4 插件中使用静态 iOS 库