typescript - 使用以 T 为条件的其他类型的类型断言来推断类型 T
问题描述
考虑这个检索“项目”或“项目”数组的函数:
function foo<T extends Item | Item[]>(id: T extends Item ? string : undefined): T {
...
}
这样做的目的是,如果您想要一个项目,则foo
使用 an调用,或者如果您想要一个项目数组,则不使用 an 调用。这很有效,因此调用者可以这样做:id
id
foo<MyItem>('42')
和
foo<MyItem[]>(undefined)
(使用可变参数可以使这一点变得更好,例如在检索数组时function foo<T extends Item | Item[]>(...[id]: T extends Item ? [string] : []): T {
启用不带参数的调用)。foo
但是,在 的实现中foo
,我注意到如果我检查 的类型id
:
if (id) { // if typeof id === 'string' gives same result
...
}
...然后在那个 if 子句中,编译器不明白该类型T
现在必须扩展Item
而不是 Item[]
(因为id
仅当 是一个字符串。如果我想调用任何依赖于 T 的代码,T extends Item
我仍然需要这样做,或者我会得到:T as Item
Item
TS2344: Type 'T' does not satisfy the constraint 'Item'. Type 'Item | Item[]' is not assignable to type 'Item'. Property 'id' is missing in type 'Item[]' but required in type 'Item'.
换句话说, 的类型id
取决于 的类型,但 T 的类型不会通过断言 that是一个字符串T
来推断/缩小。id
有可能以某种方式解决这个问题吗?这是一个简单的as
演员,但我只是好奇。
解决方案
您可以使返回类型以参数类型为条件,而不是相反:
function foo<T extends string | undefined>(id: T): T extends string ? Item : Item[] {
// ...
}
或者,如果你只想用绝对是字符串或绝对未定义的东西来调用它,你可以使用重载而不是让它泛型:这样你就可以在没有参数的情况下调用函数,而不是作为undefined
传递争论。
function foo(): Item[];
function foo(id: string): Item;
function foo(id?: string): Item | Item[] {
// ...
}
这些解决方案之间的实际区别在于,使用重载,您的函数不能使用 type 的参数调用string | undefined
,因此在编译时始终知道特定调用将解析为单个项目还是项目数组。
请注意,这两种解决方案都避免了使用类型参数调用函数Item & HTMLCanvasElement
然后返回类型不正确的问题。
推荐阅读
- python - 没有为 Pandas 查询功能定义“BACKTICK_QUOTED_STRING__AT_key”
- asp.net-core - Odata 扩展总是生成左连接
- ios - 当它不是可访问性元素时,是否可以通过其 `accessibilityId` 获取`XCUIElement`?
- android - 一次性权限导致后台计划作业和警报被取消
- reactjs - 警告:validateDOMNesting(...):不能作为. 在 gatsby js 项目中
- discord.py - 用户权限检查抛出错误,但我不知道为什么
- java - Android - 如何访问 PDF 页面的属性?
- glassfish - Payara 服务器作为服务启动
- sql - 从具有面积总和的表中选择查询
- javascript - 优化缩小 JS 的 TypeScript 编译和调试