在 TypeScript 中设置所需的函数参数

2024-01-10

在下面的代码中:

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(使用前将#替换为@)

在 TypeScript 中设置所需的函数参数 的相关文章

  • Angular 2延迟加载模块-服务不是单例

    我已经在我的应用程序中实现了延迟加载模块 app module ts 配置正确 NgModule declarations AppComponent HeaderComponent HomeComponent imports Browser
  • TypeScript 中的“环境”是什么意思

    我不明白这个词是什么意思ambient在下面的句子中 不能在环境上下文中声明函数实现 我不确定是否理解这个词的一般含义 英语不是我的母语 如果这里有什么具体含义 我也不明白 我试图用我的母语来理解 但在这种情况下无法理解 这就像curren
  • 如何重启ngOnInit来更新Interpolation

    有办法重新启动吗ngOnInit 改变变量时 因为我想重新开始ngOnInit 改变时theme多变的 这是我的代码 设置 ts export class SettingsPage implements OnInit phraseColor
  • Angular 2 兄弟组件通信

    我有一个列表组件 当在 ListComponent 中单击某个项目时 该项目的详细信息应显示在 DetailComponent 中 两者同时出现在屏幕上 因此不涉及路由 如何告诉详细组件列表组件中的哪个项目被单击 我考虑过向父级 AppCo
  • `Account` 是 TypeScript 中的保留字吗?

    我很困惑 以下 TypeScript 代码无法编译并出现此错误 fails ts 10 7 error TS2420 Class Account incorrectly implements interface IAccount Prope
  • 错误 TypeError:无法使用角度 6 读取 ngx-bootstrap 中 null 的属性“createText”

    我想使用以下命令从不同的组件打开 ngx bootstrap 模式 ViewChild在角度 6 但我收到此错误 错误类型错误 无法读取 null 的属性 createText 在 ComponentLoader push node mod
  • 获取不正确的日期,将时间戳转换为新日期

    我正在尝试将时间戳转换为日期 但得到的日期不正确 我正在开发一个使用 Angular 和 Typescript 的项目 我有这样的时间戳 1451642400 2016年1月1日 和1454320800 2016年2月1日 如果我编码 da
  • minLength 在打字稿中不起作用,反应

    我在 下一步 中有一个输入 打字稿 Maxlength 确实有效 但 minlength 现在不起作用 有人如何验证这两者吗 这是我的代码
  • 从 *ngIf Angular 5 调用函数

    假设我这里有这段代码 div lorem ipsum div 如果 ngIf 计算结果为 true 有没有办法可以调用函数 你知道这样的事情 div lorem ipsum div 任何帮助 将不胜感激 Thanks 角度方式是 div d
  • Angular 2 反应形式的嵌套数组?

    我使用以下教程在 Angular 2 中创建反应式表单 效果很好 https scotch io tutorials how to build nested model driven forms in angular 2 https sco
  • 如何从 typescript 使用 npm 模块?

    我正在尝试打字稿 它在 hello world 阶段运行良好 我现在尝试使用 npm 模块 index ts import require lodash console log toUpper Hello world 这不起作用 tsc i
  • 跟踪滚动位置并通知其他组件

    有没有一种简单的方法来跟踪浏览器滚动位置并通知多个组件 用例 在滚动时 我希望能够根据我所在的位置更改页面上各种元素的类 在 Angular 的早期版本中 通过插件可以实现这一点 对于 jQuery 也是如此 当然 可以选择编写裸 JS 在
  • 更新到 Angular 6 和 rxjs 6 后 Plunker 损坏

    我有一个Plunker 中的 Angular 应用程序 https embed plnkr co 1dAIGrGqbcfrNVqs4WwW 自从我升级我的应用程序以使用 Angular 6 和 rxjs 6 以来 它不再起作用 这是我的co
  • React 16.7 - React.SFC 现已弃用

    我用来声明无状态组件 如下所示 const example React SFC
  • TypeScript AngularJS 组件模态 - this.$modalInstance.dismiss 不是一个函数?

    我已将其中一个用户数据输入表单转换为 uib 模式 但是当我尝试从 取消 按钮关闭模式时 出现以下错误 this modalInstance dismiss is not a function 同样的事情是如果使用this modalIns
  • 如何同时模拟Pinia和vue-i18n?

    我正在使用 Vue 3 的 Composition API 如下所示 store ts import ref Ref from vue import defineStore from pinia export const useStore
  • 具有相同父布局角度的功能模块路由

    我想使用相同的布局 在应用程序模块 ts 对于不同的功能模块 每个模块都有自己的路由 以及一个单独的登录 注册布局 没有侧面菜单 页眉和页脚 到目前为止我尝试过这个 app app component html
  • 在 Typescript 中创建动态变量引用

    提前感谢任何提供帮助的人 对于有经验的人来说 这似乎是一个简单的答案 但我已经浏览了互联网和几本参考书 并没有找到这个问题的直接答案 所以希望它也对其他人有帮助 我目前正在从 Actionscript 过渡到 Typescript 并且对普
  • 打字稿日期格式

    我正在使用角度 2 4 我怎样才能将日期格式化为这个2017 10 03T14 51 06 078Z 下面是我的代码 public today number Date now console log today time this toda
  • 使用 @nomiclabs/hardhat-waffle 实现装置

    在官方华夫饼文档中 您可能会找到实现装置的下一种方法 import expect from chai import loadFixture deployContract from ethereum waffle import BasicTo

随机推荐

  • python pandas dataframe 聚合 groupby

    我的 pandas DataFrame 有很多行和列 这里只显示三行 date place number 2010 LON 10 2010 BER 20 2010 LON 5 2011 LON 10 2011 BER 15 2011 BER
  • 比较两列,并返回 Excel 中的特定相邻单元格

    我正在使用以下组合if vlookup match iserror函数 不幸的是我没能找到正确的公式 比较两列的匹配情况非常容易 困难的部分是在找到匹配项后返回特定的单元格 所以我正在处理的是这样的事情 Header Column A Co
  • iOS 10 不调用通知服务扩展

    我尝试实现新的通知服务扩展 但遇到问题 在我的NotificationService swift 文件中 我有以下代码 class NotificationService UNNotificationServiceExtension var
  • 在android studio中的所有活动中保留帐户信息

    我的应用程序只是一个管理数据库应用程序 我设置了一个远程 mysql 服务器 我的 android studio 应用程序使用 http post 请求连接到该服务器 假设我想在所有活动中保留用户名 密码等帐户信息 现在我使用 putExt
  • CUBA:实体继承

    提供的示例 实体继承 具有以下实体模型 顾客 公司拓展客户 人扩展客户 命令 OrderEdit 屏幕显示如何处理与客户 可以是公司或个人 关联的字段的继承 这是非常清楚的 但是 公司和个人的编辑屏幕不考虑继承 它们只是复制通常从客户继承的
  • 为什么线程 10000 次 start() 调用比 10000 次 run() 调用花费更多时间?

    我正在线程上做一个 hello world 我使用以下命令创建了一个简单的线程run 调用 这只是一个普通的方法调用 和一个使用 start 调用的重复线程 它会生成另一个线程来处理 但是 start 通话次数多于run 调用 这不是线程调
  • 使用Maven部署后如何运行测试?

    我正在尝试决定如何为 Java EE Web 应用程序创建一组验收测试 设置如下 Maven 用于生成 WAR 文件并将其部署到 Glassfish 中 部署时 MySQL 数据库架构会使用 Hibernate hbm2ddl auto 选
  • 将 Prawn PDF 保存为回形针附件?

    我使用 Prawn 和 Prawnto 向用户显示基于 PDF 的报告 但在某些情况下 我还想将 PDF 保存为我的模型之一的附件 我所有的附件都使用回形针 有人对如何做到这一点有任何建议吗 Thanks 使用 prawnto 时 您需要评
  • :not(:first-child) 和 :not(:first-of-type) 不起作用

    我有一个树系统 我想做的是给除了第一个父母之外的所有父母留出余地 这是我的 HTML div div class theBody div class someContainer div class someItemClass Test di
  • 如何使用JPA持久化LocalDate?

    我想将没有时间的日期存储到我的数据库中 所以 我选择使用LocalDate type 正如这篇文章中提到的 如何使用 JPA 持久保存 LocalDate 和 LocalDateTime2 1 https thoughts on java
  • 如何向 Python 单元测试提供标准输入、文件和环境变量输入?

    如何在出现以下情况时编写测试 测试用户输入 测试从文件读取的输入 测试从环境变量读取的输入 如果有人能告诉我如何处理上述场景 那就太好了 如果您能给我指出一些我可以的文档 文章 博客文章 那就太棒了 读 您所描述的所有三种情况都是您需要特别
  • 带有大文件的 Amazon s3 上的 dask read_csv 超时

    s3 上的 dask read csv 大文件超时 s3fs S3FileSystem read timeout 5184000 one day s3fs S3FileSystem connect timeout 5184000 one d
  • 无法在 MLEngineTrainingOperator 中指定 master_type

    我正在使用气流来安排管道 这将导致使用人工智能平台训练 scikitlearn 模型 我用这个 DAG 来训练它 with models DAG JOB NAME schedule interval None default args de
  • hasNext 不适用于 javascript 中的集合

    我在 javascript 中有以下代码 它检索两行 var raceCursor RacesCollection find eventId e1 var race while raceCursor hasNext race raceCur
  • LibXtract 的 Android.mk

    有人可以帮我为 LibXtract 编写 Android mk 或为我指出正确的方向吗 这是 lib 的来源 https github com jamiebullock LibXtract git https github com jami
  • 在 Google App Engine Python 中存储值的最简单方法?

    我很懒 我只想存储一个字符串值 就这样 我可以跳过任何类型的建模并只存储一个值吗 据我所知 DataStore 是 App Engine 上唯一可用的存储 然而 即使你很懒 代码也不是很多 确保导入db module from google
  • jupyter 笔记本中的 PYSPARK_PYTHON 设置被忽略

    我一直在尝试从 jupyter 笔记本 使用 jupyter 实验室 设置 PYSPARK PYTHON 以使用特定的 conda env 但我找不到使其工作的方法 我找到了一些使用的示例 import os os environ PYSP
  • 如何在 cookie 中存储字符串并检索它

    我想将用户名存储在 cookie 中 并在用户下次打开网站时检索它 是否可以创建一个在浏览器关闭时不会过期的 cookie 我正在使用 asp net c 创建网站 我怎样才能阻止浏览器提供保存用户名和密码 写一个cookie HttpCo
  • GDB 7.6 STL 漂亮的打印与 gcc-4.8 和 mac os 10.9

    我正在努力获得所描述的漂亮印刷品here https sourceware org gdb wiki STLSupport在我的 Mac 上运行 gdb 我通过 macports 下载了最新的 gdb 并使用gcc 4 8 我加载了 gdb
  • 在 TypeScript 中设置所需的函数参数

    在下面的代码中 type NoArg void type OneArg x number void let noArg NoArg x number gt let oneArg OneArg gt 只有第一个赋值才会产生编译器错误 我理解为