具有可选扩展的通用打字稿

2023-12-22

如何使用扩展进行输入检查,使通用 ApiResBook 类型与可选道具一起使用?

Sandbox https://www.typescriptlang.org/play/index.html#code/PTAEFkEMEsDtQC4E8AOBTAzqSW6gCaQKQBGOaoAtKBgBYD2ArgDb4DkCoJFAxrZLADmafAFgAUMnSgAQvXoBrUAF5QAbwmhQ0fAC4aCAE5xBmxNATM0+jEZNmAbtAzQSV-SXlWBZyIwQMhjZ2QhIAvhISUhQAgv6BKupmOsHGoeJasJAAttYGaabiEeISIKAAkrC0aIZoCCKgAGaG9NmIqJhNLW3ZMLBRHbLyCgBi0GisWKoKaEj0jUOKA9JxAfSGYxP4U6AzcwurgZHiZdFN66DCsDVEJqBoAB7oPPX4TXV8oLUYKPSwGBRmq1QDEAArlZaxFDQABKmDkigAPGZQdAeDN8AjRuNJvcHvVYNtFtithgADQotEYw7rTa4x4Eok0jY4okAH1AjEJaEacAaqi5+B5fPwFPEAD5EhoMlxhvpUejEViyaAFRisXTtpKAGRJGVaPxrQwAfnlVJEzM1WAZaEJWEtrKwxtVVMRzJVaot8Vpjsl+kFwuuYhlxWKpTAjQ+tDxORQVlA805GEgwgkOCQsB4TS5L2gfyasAAFABKPVmHh-WzvBB8MHlRKIgCiTzQLxEABEiJBEgIkOLC2YDdCYrm-qkTGKtFpPPgkPpe2Zi-Lus40Ii1AQu-pm89Xp3iKAwqAORuai0gohDIwKGFJcpJdKp186oxDPBrgB3VUrgGFwvfehmAcNBS3vPUny0SMa1oQsAANIGhWCVRnJBi0HCCADoAltP9DEgD9QMlPCPwwgArDA-hLND9Uw7Ci0LFBIEMAE9HUTdiG3Fs23wfduyPE97kMc99CMa9D0I58KKAtAGKYlji2oiCpwwngiD4P8zwkx8lKnCt-kAtAMOYehBELTT0KfMJFKnKyzDDGUym+X5-goM5nDYs91hEq8KEPY91EIDi2M8RR9A3FJ8juI9ovLStOCcysKFUfCYE4KDa3BN1oThDAsURNgdDYcV+zYDBsgCNgVTUKzQHCY56pOMB6lsDBIWJAB5WBmCQRIYmy+FhnywrxTarEAHULFoZlev63LBoK9gVTYLJciK44yjoJhWC4CglnEPSqxChROu6-QsROnrVA3I6wu0Vi2AARjYPzigOzgjomgJmTO4ZPqm71DClWVQrYiLHsq7AAdula8jYKAHme6LD3WsBNpYN5uEE89RuGC7GyEi5VD62EBqRNgUBaFB23oTBYAQZtnAQNbJEGcbJuZfHzxmkm5rJwqlop+gqZpjA6YZ2xmbe4Hjq6pBOa8jrZaBm7Qfup6VUNQIwph-Q4cgBGkaPCQpY+yamAQDmCYvNmvoBqUVbUMGnrCI8gA.

我有这样的主要类型,与数据库字段相同:

// Main types as in database - should't be changed
type Book = {
  id: string
  title: string
  visible: boolean
  author: string
}

type Author = {
  id: string
  name: string
}

对于 api 获取响应,我需要通用类型,该类型将根据请求的字段塑造对象

// Inhereted from types from main
type BookFields = keyof Book
type AuthorFields = keyof Author

// type for generating expected fetch response from API
type ApiResBook<
  PickedBookFields extends BookFields,
  PickedAuthorFields extends AuthorFields | undefined = undefined,
> = {
  book: Pick<Book, PickedBookFields> & {
    author?: PickedAuthorFields extends AuthorFields ? Pick<Author, PickedAuthorFields> : undefined
  }
}

// fetch example of usage
async function fn() {

  const fetchAPI = <ExpectedData = any>(
    apiAction: string,
    body: any
  ): Promise<{ data: ExpectedData } | { error: true }> => {
    return new Promise((resolve) => {
      fetch(`api`, body)
        .then((raw) => raw.json())
        .then((parsed: { data: ExpectedData } | { error: true }) => resolve(parsed))
        .catch((err) => {
          console.log(err)
        })
    })
  }

  // response type is { error: true  } | {data: { book: { id: string } } }
  const response = await fetchAPI<ApiResBook<'id'>>('smth', {}) 
}

问题在于通用 ApiResBook 类型,我不知道如何使某些通用类型可选。测试示例包括:

//tests
type BookOnly = ApiResBook<'id'>
type BookWithAuthor = ApiResBook<'id', 'name'>

// should be ok
const bookOnly: BookOnly = { book: { id: '1' } }
const bookWithAuthor: BookWithAuthor = { book: { id: '1', author: { name: 'Max' } } }

// should be error
type BookOnly2 = ApiResBook<'propFoesntExist'>
const bookOnlyError: BookOnly = { book: { id: '1', author: {name: 'Max'} } } 
const bookWithoutAuthorError: BookWithAuthor = {book: {id: '1'}} 

我自己解决了这个问题:/似乎工作正常。

type ApiResBook<
  PickedBookFields extends BookFields,
  PickedAuthorFields extends AuthorFields | undefined = undefined,
> = {
  book: Pick<Book, PickedBookFields> & {
    author: PickedAuthorFields extends AuthorFields ? Pick<Author, PickedAuthorFields> : undefined
  }
}

.

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

具有可选扩展的通用打字稿 的相关文章

随机推荐

  • easy_install 安装了各种版本的 python、mac osx

    我在 mac OSX 10 6 机器上有各种版本的 python 其中一些安装了 macports gt python select l Available versions current none python24 python26 p
  • 如何防止命令行参数由 R 解释而不是仅由我的脚本解释?

    我正在使用docopt https github com docopt docopt RR 的实现 我的脚本有一个命令行选项 其缩写形式为 g 当我运行我的脚本时 似乎这个参数首先由 R 解释 然后由我的脚本解释 因此 我因为没有为 GUI
  • SoapClient 尝试获取架构文件时出现 401 身份验证错误

    我的应用程序通常连接到第三方服务器以通过 SOAP WSDL 获取数据 this gt soap client new SoapClient https the domain 443 path wsdl array trace gt 1 l
  • 如何优化 EF Code First 查询?

    已更新 请参阅底部的更新 我使用 EF 代码优先 并且总体上对此感到满意 然而 一个简单 且常见 的操作导致 EF 生成极其复杂的 SQL 这降低了我的应用程序的速度 我只是使用 整数 ID 列表来获取一组实体 但因为我需要大量子实体的详细
  • 在 C++ 中前向声明静态 C 结构实例

    我正在编写一个代码生成器 实际上是一个数据生成器 它将生成这种形式的数据结构 显然实际的数据结构要复杂得多 typedef struct Foo int a struct Foo foo Foo extern Foo f1 extern F
  • 使用 Pandas Excelwriter 写入 StringIO 对象?

    我可以将 StringIO 对象传递给 pd to csv 就好 io StringIO StringIO pd DataFrame to csv io 但是当我使用excel writer时 我遇到了很多麻烦 io StringIO St
  • jQuery serializeArray() 键值对

    我在序列化表单时遇到了一些麻烦
  • Bootstrap 一次轮播多个框架

    这是我试图用 Bootstrap 3 轮播实现的效果 它不是一次只显示一帧 而是并排显示 N 帧 然后 当您滑动 或自动滑动时 时 它会像以前一样移动幻灯片组 这可以吗与 bootstrap 3 的轮播 我希望我不必去寻找另一个 jQuer
  • 检查 MongoDB 文档中是否存在多个字段

    我正在尝试查询一个数据库集合 该集合保存具有特定字段的文档的流程文档 为简单起见 想象以下通用文档模式 timestamp ISODate result1 pass result2 fail 现在 当一个进程启动时 会插入一个仅包含时间戳的
  • 在继续当前脚本的同时异步运行单独的 PowerShell 脚本

    PowerShell 脚本 1 执行以下操作 Performs FTP ops ending with saving updated remote directory data in a local file 该脚本快速运行 直到必须使用
  • WPF 全局字体大小

    我正在创建一个 WPF 应用程序 我想知道能够更改 ui 中每个元素的字体大小的最佳方法 我是否创建资源字典并设置样式来设置我使用的所有控件的字体大小 最佳实践是什么 我会这样做
  • CSS3 月亮形状

    我正在尝试创建一个像这样的按钮 我不知道如何在按钮顶部创建一个浅月形状 这还很遥远 小提琴演示 https jsfiddle net wgnp9ygh 2 moon width 50px height 50px border radius
  • 软删除 - 使用 IsDeleted 标志还是单独的连接表?

    我们应该使用软删除标志还是单独的连接表 哪个更有效率 数据库是SQL Server 背景资料 不久前 我们有一位数据库顾问进来查看我们的数据库架构 当我们软删除一条记录时 我们将更新相应表上的 IsDeleted 标志 有人建议不要使用标志
  • .NET Core 2.1 Swashbuckle - 按区域对控制器进行分组

    我的情况比较简单 我有一个非常大的 NET Core 2 1 MVC WebApi 分为几个区域 代表我系统的不同模块 我使用 Swagger SwashBuckle 效果非常好 我的路由就像 area controller action
  • 从 Java 运行“who -m”命令会产生空结果

    我正在尝试从 Java 中查找当前登录的用户名 Process p try p Runtime getRuntime exec who m p waitFor BufferedReader reader new BufferedReader
  • Perl 中的命名参数

    我正在尝试在 Perl 中使用命名参数 我一直在使用http perldesignpatterns com NamedArguments http web archive org web 20160920193219 http perlde
  • LazyEvaluation的性能优势到底从何而来?

    在过去的几天里 我研究了惰性评估 主要是在性能方面 想知道LazyEvalutaion 的性能优势由此显现 我阅读各种文章并不清楚 但其中很少包括 惰性求值有什么优点 https stackoverflow com questions 21
  • Scrapy 中的内存泄漏

    我编写了以下代码来抓取电子邮件地址 用于测试目的 import scrapy from scrapy contrib spiders import CrawlSpider Rule from scrapy contrib linkextra
  • 如何在jquery中创建调用事件的快捷键?

    如何创建在 jQuery 中调用事件的快捷键 就像我按Alt A然后调用按钮单击函数 但不是如果Alt V A 我不知道这是否是最好的解决方案 但也许有帮助 警告 这不是经过实战考验的解决方案 var pressedKeys documen
  • 具有可选扩展的通用打字稿

    如何使用扩展进行输入检查 使通用 ApiResBook 类型与可选道具一起使用 Sandbox https www typescriptlang org play index html code PTAEFkEMEsDtQC4E8AOBTA