TypeScript:基于布尔选项参数的返回类型缩小

2023-12-01

我正在尝试为我的函数创建一个类型,以便返回类型根据传递给它的值而变化。我考虑过Typescript 返回类型取决于参数接下来(几乎)这封信似乎效果很好。 然而,在我的项目中,我必须使用箭头函数。另外,如果可能的话,我想避免过载。考虑这个签名和实现:

type CreateDocumentListOptions = {
  withVersions?: boolean;
};

type CreateDocumentList = (
  options?: CreateDocumentListOptions
) => CreateDocumentListOptions["withVersions"] extends true
  ? DocumentWithVersions[]
  : Document[];

const createDocumentList: CreateDocumentList = ({
  withVersions = false
} = {}) =>
  times(
    withVersions ? createDocumentWithVersions : createDocument,
    chance.natural({ min: 1, max: 10 })
  );

当我这样调用该函数时:

const documentList: DocumentWithVersions[] = createDocumentList({
  withVersions: true
});

正如 TS 所认为的,我发现类型不匹配createDocumentList返回一个Document[]不是想要的DocumentWithVersions[]。我的印象是,使用三元运算符足以让 TS 理解返回类型会根据其条件而改变。

For the complete editable example: Edit pedantic-newton-xx4sp


如果您放弃重载,但仍然想要一个根据参数切换的返回类型,那么您将需要使用generic函数返回一个条件类型。例如:

type CreateDocumentList = <B extends boolean = false>(
    options?: { withVersions?: B }
) => B extends true
    ? DocumentWithVersions[]
    : Document[];

这里是泛型类型参数B is 受约束的 to boolean and defaults to false。然后,取决于是否B is true or false,输出是DocumentWithVersions[] or Document[].


返回条件类型的泛型函数的一个警告是,在函数的实现内部,编译器无法验证您所做的事情是否安全。在哪里B是一个未指定的泛型,编译器defers评估B extends true ? ...,这意味着它无法看到任何特定值何时与类型匹配。这个痛点是公开问题的主题微软/TypeScript#33912.

const createDocumentListOops: CreateDocumentList = (({
    withVersions = false
} = {}) =>
    times(
        withVersions ? createDocumentWithVersions : createDocument,
        chance.natural({ min: 1, max: 10 })
    )); // error!
// Type 'Document[]' is not assignable to type 
// 'B extends true ? Required<Document>[] : Document[]'

除非采取任何措施来解决这个问题,否则这意味着您将需要使用类型断言或类似的方法以避免实现中的编译器错误:

const createDocumentList = (({
    withVersions = false
} = {}) =>
    times(
        withVersions ? createDocumentWithVersions : createDocument,
        chance.natural({ min: 1, max: 10 })
    )) as CreateDocumentList; // okay

现在我们可以测试调用createDocumentList()按照你的意愿行事:

const documentList = createDocumentList({ withVersions: true });
// const documentWithVersionsList: Required<Document>[]

const documentList1 = createDocumentList();
// const documentList1: Document[]

const documentList2 = createDocumentList({ withVersions: false });
// const documentList2: Document[]

const documentList3 = createDocumentList({ withVersions: Math.random() < 0.5 });
// const documentList3: Document[] | Required<Document>[]

看起来不错。注意documentList3 is a union的类型,因为withVersions输入的属性是boolean,这是并集true | false,以及返回类型createDocumentList() is 分配性的超过工会。这可能是也可能不是您想要的行为,但在我看来这是合理的。

Playground 代码链接

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

TypeScript:基于布尔选项参数的返回类型缩小 的相关文章

随机推荐

  • 为什么不能在 for 循环内操作“i”[重复]

    这个问题在这里已经有答案了 为什么 for i in range 10 i 1 print i return 1 2 3 4 5 6 7 8 9 10 代替 2 4 6 8 10 如果需要更多细节 这里将提供一些细节 for i in ra
  • php scandir 产生额外的元素(2 个点)

    Hi 我在名为 content 的目录中有以下文件 index php page1 php page2 php 和 page3 php 然后我有这个代码 column scandir content foreach column as va
  • 在VLOOKUP中动态更改源工作簿的文件路径

    我想要一个包含文件路径的单元格 C Documents Costs Costing 2017 xls Sheet2 A D 将用于VLOOKUP在工作簿其余部分的不同工作表中发挥作用 目前 我的文件路径位于名为 Master Sheet 的
  • 获取二进制文件 C 的哈希值

    我想获取我所知道的名称的二进制文件的哈希值 我尝试过以下方法 但后来意识到SHA1 返回字符串 文件名 的哈希值 但我想在文件本身上运行它 任何关于如何做到这一点的指示都会很棒 char fileName bin ls unsigned c
  • scalaz 中的类型类和继承

    这是我第二次尝试定义问题 我无法理解它 我希望能够定义一个代数类型并在其上定义一个简单的类型类 比方说Show 在哈斯克尔我做 data Tree a EmptyTree Node a deriving Show 现在 如果我输入Empty
  • 使用 Linq 从 IEnumerable 中提取数据并将其存储在数据表中

    我有一个如下所示的数据表 public static DataTable SetColumnHeaders DataTable KeyDataTable KeyDataTable Columns Add First Name typeof
  • 在内联 html img 标签中显示带有图像标签的 SVG

    为了将 SVG 转换为 PNG 我将 svg insideHTML 内容放入 img 标签中 如下所示 img src gt SVG 图片无法正确显示 尤其是 SVG 标签内的图片 如下所示 其他 svg 标签正确显示
  • 尝试为文件 附加自动命名数据库失败。存在同名数据库

    我的项目的 App Data 文件夹中有 ASPNETDB MDF 数据库 当我尝试添加用户时出现错误 MembershipUser user Membership CreateUser viewModel Username viewMod
  • MVC2 RTM - 使用实体框架模型绑定复杂对象

    我是 MVC 新手 并且真的很挣扎于我认为这应该是一个非常常见的场景 我正在使用 MVC2 RTM 和模型对象的实体框架 我正在做的工作 包含子对象集合的父对象的编辑视图 该表单显示父对象的所有可编辑字段 并迭代并显示所有关联子对象的所有可
  • Wordpress - 无需插件即可按视图获取 5 个热门帖子

    Hi 我有自定义字段 其中包含帖子中的图像 并且我想显示按视图排序的前 5 个帖子 我正在使用 WordPress 您能帮我吗 对不起 我的英语不好 Thanks 有一个错误Xhynk的参考 它运行的查询按字母顺序返回帖子 1 2 20 2
  • Postgres - 使用 postgis 计算距离

    经过几天的寻找 并尝试了我找到的所有内容后 我来这里询问如何使用 PostGis 计算 Postgres 上两点之间的距离 我有一张名为 位置 的表 该表有一个点类型的 坐标 列 当用户在应用程序上插入值时 我需要获取按近距离排序的位置 我
  • 从对象字典创建 Django 表单

    我觉得这一定很简单 但经过几天的尝试 我正式一无所知 我有一个字典 其中键是对象 值是对象列表 以下是我想如何使用该信息来构建表单 for object in dictionary name of field object slug nam
  • 如何从 iPad 键盘上删除或禁用特定文本字段的语言首选项键

    1 需要从 iPad 键盘上删除或禁用特定文本字段的按键 如图所示 设置在故事板中 或手动 textField setKeyboardType UIKeyboardTypeASCIICapable
  • 使用 PHP 重写 URL

    我有一个如下所示的网址 url com picture php id 51 我该如何将该 URL 转换为 picture php Some text goes here 51 我认为 WordPress 也有同样的作用 如何在 PHP 中创
  • 应用程序无法在 WAMP 上运行,但可以在在线服务器上运行

    我使用在线 SQLite 数据库制作了一个基本的登录应用程序 http demo3534535 16mb com 它在在线服务器上运行良好 现在我想在 Gennymotion 模拟器中使用 WAMP 在本地服务器上运行 我必须对代码进行哪些
  • 带有 where 子句的 SQL select 语句

    如果没有硬编码值 我将如何编写这个 sql 语句 resultSet statement executeQuery select from myDatabase myTable where name john this works 而是有类
  • 为什么改变块和网格大小会对运行时间产生如此大的影响?

    我正在研究一些cudatutorial将 RGBA 图片转换为灰度图 但我不明白为什么要改变blockSize and gridSize改进了 X33 时间 global void rgba to greyscale const uchar
  • 用 C# 创建 VPN 客户端 [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我一直在研究不同的 VPN 它们似乎没有很好的加密 如默认的 Windows XP VPN 服务器 我想看看是否可以使用 C 创建自己的 但我不知道如何创建一个客户端来拦截所有数
  • 如何以不同的顺序对嵌套列表中的 data.frame 对象集进行分组?

    我在嵌套列表中有一组 data frame 对象 我想按 data frame 对象的名称对它们进行分组 因为每个嵌套列表 data frame 对象都以不同的顺序放置 所以我很难将它们分组到新列表中 我尝试了 CRAN 中 purr 包的
  • TypeScript:基于布尔选项参数的返回类型缩小

    我正在尝试为我的函数创建一个类型 以便返回类型根据传递给它的值而变化 我考虑过Typescript 返回类型取决于参数接下来 几乎 这封信似乎效果很好 然而 在我的项目中 我必须使用箭头函数 另外 如果可能的话 我想避免过载 考虑这个签名和