Typescript - 逐步扩展对象的类型

2024-04-04

我试图通过 TS 实现以下目标:

let m: Extendable
m.add('one', 1)
// m now has '.one' field
m.add('two', 2)
// 'm' now has '.one' and '.two' fields

我熟悉通过以下方式在 TS 中返回扩展类型:

function extend<T, V>(obj: T, val: V): T & {extra: V} {
    return {
        ...obj,
        extra: val
    }
}

现在,我的案例有两个问题:

1)对象m需要在之后更新其类型add()已被调用以反映新字段的添加

2)新字段的名称被参数化(并不总是extra e.g.)

第一个问题可以通过使用类定义并以某种方式使用来解决TypeThis实用程序来重新调整类型,但我无法找到足够的有关如何使用它的文档。

欢迎任何帮助或指导。谢谢!


TypeScript 3.7 推出断言函数 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions它可以用来缩小传入参数的类型,甚至this。断言函数看起来有点像用户定义的类型保护 https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards,但是你添加一个asserts类型谓词之前的修饰符。这是您可以实施的方法Extendable作为一个班级add()作为断言方法:

class Extendable {
    add<K extends PropertyKey, V>(key: K, val: V): asserts this is Record<K, V> {
        (this as unknown as Record<K, V>)[key] = val;
    }
}

你打电话时m.add(key, val)编译器断言m将有一个属性,其键的类型为key以及类型对应的值val。使用方法如下:

const m: Extendable = new Extendable();
//     ~~~~~~~~~~~~ <-- important annotation here!
m.add('one', 1)
m.add('two', 2)

console.log(m.one.toFixed(2)); // 1.00
console.log(m.two.toExponential(2)); // 2.00e+0

这一切都按您的预期进行。打电话后m.add('one', 1),你可以参考m.one没有编译器警告。

不幸的是有一个相当重要的警告 https://github.com/microsoft/TypeScript/pull/33622;断言函数仅在具有显式注释类型时才起作用。根据相关拉取请求 https://github.com/microsoft/TypeScript/pull/32695,“这个特定规则的存在使得潜在断言调用的控制流分析不会循环触发进一步的分析。”

这意味着以下内容是错误的:

const oops = new Extendable(); // no annotation
  oops.add("a", 123); // error!
//~~~~~~~~ <-- Assertions require every name in the call target to be declared with
// an explicit type annotation.

唯一的区别是类型oops is inferred to be Extendable代替带注释的 as Extendable as m是。你会收到一个错误调用oops.add()。根据您的用例,这可能没什么大不了的,也可能是一个大问题。


好的,希望有帮助;祝你好运!

链接到代码 https://www.typescriptlang.org/play/#code/MYGwhgzhAECiAeAXApgOwCZgEYmdA3gFDQnRjroA8A0tMkmujAAoBOA9gA7KuICe1ZHwA00AGoA+ABQBrIQC5o1UQDcwIRWICUiyBB6IYiABYBLGOegAlZMHasqy8RILFS7qScuRoAV1QyqOwA7qhkMDZ2DjSikloA2nJ8ALrQALzQaiAA3G4kAL6EhdCEdqgQiNAAtooIKBjYuOnQqMjBcAwNOMhSWrkA9P3u0AB+Y+MTY9CUALQz0KZVnPaIYKiVa0GriKbsYcY8yACEhFUAdOToUgDke8jXogCMWqcXFDeIwewP0ABML6U9hB2LgziB2ABzKTnO5nRDsABipngyCu-z60EG0EeZwADLjAeUQcgwZDoXCvnD2Ahlq11qZ1FJ0dlMUNfnjccgANQEwkVaDsLgwDKtdp1RiNHoYrFBMioLZgHZ7NyCzgQN5XABEYE1T1+AGZpUMeBxWCdBpNxtM5tAAIJQAy7crQVjIACOvlMrroKh4fBaYCqeFMYRMeGA6hA0FWrAhyEq8OgWDw6Fs4Fd6GgwVMJkIWLWdHgnBApmAOejfG4coVStQZ0IhCAA

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Typescript - 逐步扩展对象的类型 的相关文章

随机推荐

  • 删除 numpy 数组中的屏蔽元素

    我有一些包含屏蔽元素的数组 来自Numpy MaskedArray e g data 0 1 masked 3 masked 5 面具不遵循常规模式的地方 我想遍历数组并简单地删除所有被屏蔽的元素 最终得到 data 0 1 3 5 我尝试
  • 调试部署的azure应用程序

    是否可以附加到已部署的 Azure 应用程序 我希望能够单步执行代码 以便可以查看在对我的 Web 角色操作之一的请求中设置了哪些值 我环顾四周 唯一的例子似乎是当天蓝色应用程序在本地计算机上运行时进行调试 允许在云中使用 IntelliT
  • Objective-C 中整数的除法和四舍五入

    我有 2 个整数 如何将一个除以另一个然后再四舍五入 如果你的整数是A and B你想要 ceil A B 只需计算 A B 1 B
  • Spyder中的runfile是什么意思

    尝试在 WinPython Spyder 中使用 PyPDF2 时 我无法解释错误消息 错误信息 在 3 中 runfile C Users User Downloads WPy64 3720 pdf2text py wdir C User
  • 如何从access数据库中查询表结构?

    我想用 C 获取 Access 数据库中所有表和 odbc 数据源的结构 所以我尝试了这段代码 string text var tables GetApp CurrentData AllTables for int i 0 i lt tab
  • 使用来自另一个 Pandas 数据框的信息填充 Pandas 数据框

    我有一个 Pandas 数据框 其中包含以下信息 index year month day symbol transaction nr shares 2011 01 10 2011 1 10 AAPL Buy 1500 2011 01 13
  • 具有集群和自定义视图标记的 Google 地图在放大和缩小时滞后太多

    我要加载GoogleMap用自定义视图代替GMSMarker并想展示聚类 我已经做到了 但我在放大或缩小地图时面临着滞后和内存使用情况 我已加载自定义视图GMSMarker信息视图 这是我的代码 class InitialMapViewCo
  • 使用 3d 变换矩阵

    在人工智能课程中 我们有一个机器人 它的手臂有 7 个关节 每个关节可以向不同的方向旋转 我需要知道最后的结局在哪里 我一直在尝试进行 3d 矩阵乘法 它适用于一个关节 但一旦我添加另一个关节 它就与我使用 Java3D api 制作的模型
  • 有没有办法直接访问 CSS 网格中自动放置元素的实际网格坐标?

    还有人问了类似的问题here https stackoverflow com questions 51327802 how to get the grid coordinates of an element using javascript
  • R 取子集后得到数据框的原始索引

    子集化后是否可以获取数据框的原始索引 它存储在某个地方 但我不确定在哪里以及如何访问它 我知道如果这是算法设计的一部分 会有更好的解决方案 我只是好奇是否有人知道是否可能 示例场景 df data frame atr1 integer at
  • 保留元素的排序列表,按该元素外部的属性排序

    我有一个 管理器 类维护对象列表 每个对象都有一定的 位置 但他们不知道这一点 只有管理者知道这一点 管理器必须为每个对象分配一个位置 并维护根据此 外部属性 排序的对象列表 请注意 对象的位置可以随时更改 理想情况下 我应该能够立即获取位
  • 在JavaScript中获取两个日期之间的年、月、日差异[重复]

    这个问题在这里已经有答案了 好吧 我在这里发现了很多类似的问题 试图获取两个日期之间的年 月和日的差异 但没有答案可以满足我的要求 所以我写了一些东西来计算 它似乎有效 但也许这里的一些专家可以进行更正或帮助使这更简单 您可以使用momen
  • Magento 高级配置文件导出 - 将 URL 添加到 IMAGE 路径

    刚使用 Magento 几周 就成功地使用了高级导出配置文件 非常方便 我想做的是将 url 值添加到输出列之一 特别是图像 url 我想将 url 附加到路径输出的开头 有人可以帮忙吗
  • 可空字段在写入 Spark Dataframe 时发生更改

    以下代码从 parquet 文件读取 Spark DataFrame 并写入另一个 parquet 文件 将 DataFrame 写入新的 Parquet 文件后 ArrayType 中的 Nullable 字段的 DataType 会发生
  • DAO.Recordset、DAO.Recordsets、DAO.Recordset2 之间的差异

    谁能解释一下之间的区别DAO Recordset DAO Recordsets and DAO Recordset2在 MS Access 2007 中 基本上使用记录集 给出一个例子 以便更清楚 我从帮助选项中找到了一些参考资料 但我不清
  • 为什么我的查询只显示一个结果?

    为什么我从下面的查询中只得到一个结果 建议的 答案 的名字是 Susan 而不是我在结果中得到的名字 SELECT EmpFirstName EmpLastName p ProductName as ProductName YEAR c O
  • 分割功能 - 避免最后一个空白空间

    我对如何使用 split 功能有疑问 str James Joseph Arun str split 我得到了结果 James Joseph Arun 我需要输出为 James Joseph Arun 最好的方法是什么 要删除所有空字符串
  • Mongo数据库保存Map中的数据

    我有以下有效的代码 if aDBCursor hasNext DBObject aDbObject aDBCursor next aDbObject put title Test Title ArrayList
  • 如何仅以编程方式禁用我的应用程序的移动数据

    我正在开发一个应用程序 我担心用户之间可以传输的数据量 由于一些用户的移动数据计划有限 而另一些则没有 我想知道是否可以开发一个开关来禁用我的特定应用程序的移动数据 有点像Android自己的数据使用 gt 移动 gt 应用程序 gt 限制
  • Typescript - 逐步扩展对象的类型

    我试图通过 TS 实现以下目标 let m Extendable m add one 1 m now has one field m add two 2 m now has one and two fields 我熟悉通过以下方式在 TS