在下面的代码中:
type NoArg = {
(): void
}
type OneArg = {
(x:number): void
}
let noArg: NoArg = (x:number)=>{}
let oneArg: OneArg = ()=>{}
只有第一个赋值才会产生编译器错误。我理解为什么会出现这种情况,因为 JavaScript 允许传递函数时使用少于其完整的可能参数集,这与说参数是可选的不同,这与函数的方式有关called而不是它是怎样的passed. See the FAQ https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-functions-with-fewer-parameters-assignable-to-functions-that-take-more-parameters.
但话虽如此,有没有办法构建一个 OneArg 接口版本,not与零参数函数兼容吗?
我知道这可以通过品牌或名义打字来完成,例如,
type OneArg = {
(x:number): void
_brand: “OneArg”
}
但是,或者任何其他类型的名义类型解决方案,都需要在赋值上做额外的工作(例如,您必须显式地将 _brand 属性添加到函数中)。
所以我的问题是——有没有办法构造一个类型 NoArg ,该类型会使简单赋值失败let oneArg: OneArg = ()=>{}
?
上面链接的常见问题解答说“目前 TypeScript 中没有办法指示必须存在回调参数。”这是否完全排除了我想要在这里执行的操作?我希望不会,因为这不是回调参数,但也许原理是相同的。
更新:在下面的评论中,提出了是否可以通过类型保护测试来实现这一点的问题。据我所知,答案是否定的,因为类型重叠意味着类型保护不会缩小类型。你可以在这个游乐场 https://www.typescriptlang.org/play?#code/C4TwDgpgBA8gdhAggJwOZQLxQN4CgpQAUAHgFxwCuAtgEYTICUpUAbgPYCWAJrgL665QkKABUA7mxToseAgRLlqdZABooIUgGdgyDnFRNWnHv1wAbCMChsEUzETKVa9BhgB82fhavAJdrApOymoa2rr6rh6mAMY22lAcmvBIaPaEAGYUcNGkyVIAPuKSaIaZ2QmasLap7lBl0QB0FvrAABZQADxYAIwC9cAcNlBcidG6VHoAhsBsyIRUIABiWTlVKej5on4lOPhyAPT7IuDQqBSTyFxQrfQQajQUwA3PewQc6YSJeWjzSysMDF2cmBUGQlgoyDgUAWy2yryg-GBEDMmmgshBBDBwAhUJhK3h-FMhygzwaIgAylA2noANaVGhsNrWdJUm6oqAXaBCaBFKS4WJweILerdewjTRjDgTODTWaEGzrBj8uJWYUrABMYtG4ymMzmvmKBiAA.
经过与@aluan-haddad 的一些讨论后,我有一个部分解决方案。我无法准确得到我所要求的,即一个“自动”类型定义,它区分具有所需参数的函数和没有所需参数的函数,但我提出了一个“鉴别器”函数来区分这两个函数并应用适当的品牌类型。
该解决方案依赖于使用条件类型,再加上单参数函数与零参数类型不兼容的事实(即使反之亦然),来强制转换正确的类型。
type NoArg = {
_brand: 'NoArg'
():void
}
type OneArg = {
_brand: 'OneArg'
(x:number): void
}
// Correct typings
let noArg: NoArg = discriminator(()=>{})
let oneArg: OneArg = discriminator((x:number)=>{})
// Both of these error, as hoped!
let noArgError: NoArg = discriminator((x:number)=>{})
let oneArgError: OneArg = discriminator(()=>{})
function discriminator<T extends (x:any)=>any>(myFunc: T) {
let discriminatedFunc
if(myFunc.length === 0) {
discriminatedFunc = {
_brand: 'NoArg',
myFunc
}
}
else {
discriminatedFunc = {
_brand: 'OneArg',
myFunc
}
}
return discriminatedFunc as unknown as T extends ()=>any ? NoArg : OneArg
}
And on 游乐场 https://www.typescriptlang.org/play?#code/C4TwDgpgBAcg9gQQE4HMoF4oG8BQV9QD6ARkgIYB2AJgFxQDk8yK9eBAFAJQ0BucAllRwBfHDlCQoAeQoRmGbGxLlqdejLmpW%20dgA8aFAK4BbYhCTcofQSLEB6O1ADCcJEggBjYFAn8KKAGccABsIbwpEVDomVAUqfgCPJH5jPzJgV3YudAA%20LGFOELCoOFlmOg15THjE5NSKdMy9AxMzC1z8wpwHKAAhOGAACxKAMx9BiADocyRXABooMgCoQbhIKgBCIvDIlABRN1do3biEpJS0jKQs-SNTc04Ogu2SstQD2aQKt7Rqs7rLk1HnlnjgRoYKF5%20KUoDVzvVGkgADwAFSgEF0wAg1GWzUoIGB%20Jy7GMIAAYhCPHQUZxFAQoKFvHCAQ0sVQKZC2Ph%20CMSeTKQA6UL%20IYYdCYAAMtNw9PpzIurIg7MpChlsvVykotAYMRYcy56oIpI5HgN9NE5qgBogwSmdMN8oRbJNqrNhs1qgYlS0%20sNsuNlLd%20AtBBD%20HcwEMSAosP%20CvSSpdSygEIA1hEAO4x5NojFYnFQbI5fFQAD8sBO300KBEQA.
注意:就我而言,这依赖于与零类型函数不兼容的单参数函数,请注意条件类型的反向版本T extends (x:number)=>any ? OneArg : NoArg
不起作用,因为它总是解析为 OneArg。
现在,这比首先通过构造函数“品牌化”函数更好吗?我认为是的,因为你只需要一个鉴别器函数而不是两个品牌函数。而且还因为您不一定需要事前知道函数的签名,即当您将它们传递给鉴别器时。
有人看到这个解决方案有什么问题吗?有没有更好的,或者这都是 TS 允许的吗?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)