我正在尝试避免为外部接口上曾经是可选的属性编写空值检查,但后来在函数体上下文中被分配了默认值。我使用了类型保护,问题在于受保护的类型在一个函数中丢失,但在箭头函数中没有丢失,尽管它不能在类型保护之前提升。
我不想以类似的方式为每个函数参数引入新变量,也不想像 printMenu(options as DefinedOptions)
那样用类型转换调用其他函数。
TypeScript 版本: 3.7.3, 3.8.0-beta
搜索关键词:
typescript type guard function arrow function
代码
export interface Options {
header?: string
border?: boolean
pageSize?: number
helpMessage?: string
showKeypress?: boolean
}
interface DefinedOptions extends Options {
pageSize: number
helpMessage: string
}
const isType = <T>(arg: any): arg is T => true
export default async function menu(options: Options) {
options // Options
options.pageSize = options.pageSize ?? 0
options.helpMessage = options.helpMessage ?? 'Default message'
if (!isType<DefinedOptions>(options)) return null
options // DefinedOptions
return new Promise((resolve, reject) => {
function handleMenuKeypress(key: any) {
options // Options - should be DefinedOptions
printMenu(options) // error
}
const candleMenuKeypress = (key: any) => {
options // DefinedOptions
printMenu(options) // no error
}
})
}
function printMenu(options: DefinedOptions) {
}
Playground 链接
预期行为:
类型应该在两者中都是 DefinedOptions
。
实际行为:
函数中的类型是 Options
,而箭头函数中的类型是 DefinedOptions
。
相关:
7条答案
按热度按时间9cbw7uwe1#
这是一个简化的示例:
Playground
我认为在箭头函数内部的普通函数声明中,TypeScript过于悲观,并且
hg
应该具有与h
相同的缩小范围,即使考虑到 #32300 中讨论的内容。h4cxqtbf2#
感谢简化版本@nmain100
这里唯一的错误是
hg
,考虑到它在CFA图中的位置,应该是B
。函数表达式和函数声明的行为不同,因为一个会被提升,而另一个不会。bttbmeg03#
这是相同的错误吗?
Playground链接
如果你在playground中运行它,你会发现错误:“由于类型'false'和'true'没有重叠,这个条件总是返回'false'。(2367)”
或者我需要为这个问题创建一个新的issue吗?
kdfy810k4#
@AleksandrGilmanov 这是 #9998 的重复; typescript 不知道传递给
forEach
的函数在那个点被调用,如果所有的缩小操作在每次函数调用后都被悲观地重置,那么缩小操作基本上是无用的。acruukt95#
另一个标准案例:
http://www.typescriptlang.org/play/?ts=3.8.0-dev.20200124&ssl=1&ssc=1&pln=10&pc=2#code/GYVwdgxgLglg9mABMOcAUcAOUDOB+ALkTgCMArAU2gEpEBvAKEWOx0QF4XdEAfH+gL4BuJlxxDEAeknFyVKKIBOFKCEVI0tdgD4xE6bMrReicABMKwGGApnEAHgC0iAO6KEAcwYCGoSLAREEgBDRTRgwkQcKEVrDxNSIygAGjFIxPlaRmYYYEQ0KABPTAo4POCOdk4AcgzoatoAbWDUrFwAXQ5ERvNLa1tU4PaRZmD9GWjYsHj+XqsbMyUVNQ0tXTGpCZi4kzn+u346qAdnN09vIA
l7mqbcuq6#
你好!
有人能看一下 this playgroud 吗?我在文件底部留下了关于错误的适当评论。我的这个问题似乎部分与此相关,尽管它不是关于函数类型(函数声明或函数表达式)。
我应该创建一个单独的问题还是它们是相关的?
提前感谢。
nuypyhwy7#
其他一些更新可能已经部分解决了这个问题,因为我在4.5.4版本上得到了以下结果:
这似乎是原始问题。然而,当Assert一个对象的成员时,它仍然失败,但非常令人困惑。类型注解来自VSCode悬停在TS 4.5.4上的提示:
编辑:目前找到了一个暂时可行的解决方法,我觉得还不错: