微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何为所有3种可能的参数定义创建类型,以及如何调用期望其中任何一个的函数

如何解决如何为所有3种可能的参数定义创建类型,以及如何调用期望其中任何一个的函数

(类型来自@ type / markdown-it) https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/markdown-it/lib/index.d.ts#L93

我想为markdown-it use方法的可能参数创建参数类型,其类型如下:

type PluginSimple = (md: MarkdownIt) => void;
type PluginWithOptions<T = any> = (md: MarkdownIt,options?: T) => void;
type PluginWithParams = (md: MarkdownIt,...params: any[]) => void;

我有一个反应钩子,我想像这样递给markdown-it插件

type Plugin = MarkdownIt.PluginSimple |
  [MarkdownIt.PluginWithOptions,{}?] | 
  [MarkdownIt.PLuginWithParams,...any[]]
type Plugins = Plugin[]

function useMarkdown(source: any,plugins?: Plugins) {
  React.useEffect(() => {
    plugins?.forEach(plugin => md.use(...plugin))
  },[md,plugins])
}

首先,我不知道如何将模板参数添加到第二个插件定义中。

这不起作用:

[<T = any>MarkdownIt.PluginWithOptions<T>,T?]

但是大多数情况下,我希望TS编译器认识到使用md.use(...plugin)是安全的。 它抱怨说,论点需要支持

Expected at least 1 argument,but git 0 or more An argument for 'plugin' was not provided. Type 插件 must have a '[Symbol.iterator]()' method that returns an interator

更改我的行以手动处理数组案例:

plugins?.forEach(plugin => Array.isArray(plugin) ? md.use(...plugin) : md.use(plugin))

删除了迭代器错误消息,但其他消息也留给了...plugin

解决方法

您正在使用扩展语法将所有三种情况传递给md.use,因此它们都必须是元组。对于PluginSimple,参数是长度为1的元组。

type Plugin = [PluginSimple] |
  [PluginWithOptions,any] | 
  [PluginWithParams,...any[]]
type Plugins = Plugin[]

现在由于需要一个或多个参数的错误,我们可以通过将元组中的第一个条目与其余元素分开来进行结构化,以确保打字稿知道始终存在至少一个参数。根据我们的联合类型,我们知道main总是被定义并且是插件类型之一,而其余的是any[],对于简单的插件将是[]

function useMarkdown(source: any,plugins: Plugins = []) {
  React.useEffect(() => {
    plugins.forEach(plugin => {
      const [main,...rest] = plugin; 
      md.use(main,...rest)
    })
  },[md,plugins])
}

这不是完美的,因为我们没有在PluginWithOptions和它的特定选项类型之间强制匹配,但是希望它对您的用例足够好。对于更高级的键入,我会考虑定义自己的插件对象,该对象包含一个插件及其参数,而不是使用元组。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。