我正在处理一个类PlaybackControl
,我用它来创建两个HTMLEElement:
PlaybackControlButton: HTMLButtonElement
个PlaybackControlMenu: HTMLDivElement
个
现在,要初始化类对象,我需要三个参数:videoPlayer: HTMLVideoElement
个playbackRates: PlaybackRates
个options: PlaybackControlOptions
个
其中:
type Shortcuts = Record<string, { key: string, value: string }>
type PlaybackRates = string[]
interface ShortcutsEnabled {
enableShortcuts: true
shortcuts: Shortcuts
}
interface ShortcutsDisabled {
enableShortcuts: false
}
interface DefaultOptions extends ShortcutsEnabled {}
type PlaybackControlOptions = DefaultOptions | ShortcutsDisabled
字符串
另外,我为它们都设置了默认值,
videoPlayer
默认为document.querySelector('video') as HTMLVideoElement
playbackRates
默认为静态属性PlaybackControl.DEFAULT_PLAYBACK_RATES
options
默认为{ enableShortcuts: true, shortcuts: PlaybackControl.DEFAULT_SHORTCUTS }
现在,我想创建一个重载的构造函数,它应该在所有情况下都能工作:
1.未传递参数
1.传递的参数的任何组合任何未给出的值都应回退到其默认值,
最后,videoPlayer: HTMLVideoElement
是唯一一个我想作为类属性存储的参数,其余两个只是我想在构造函数中进行一些函数调用的参数(因为我以后不会用到它们)。
目前,我写的构造函数是:
constructor (videoPlayer?: HTMLVideoElement, playbackRates: PlaybackRates = PlaybackControl.DEFAULT_PLAYBACK_RATES, options: PlaybackControlOptions = { enableShortcuts: true, shortcuts: PlaybackControl.DEFAULT_SHORTCUTS })
型
虽然这确实允许我在没有任何参数的情况下初始化,但当我试图:new PlaybackControl({ enableShortcuts: false })
个
VSCode显示错误:
Object literal may only specify known properties, and 'enableShortcuts' does not exist in type 'HTMLVideoElement'.
型
虽然我确实理解潜在的问题(我猜),但我无法解决这个问题。任何帮助都很感激。
编辑:
1.因为,口头描述可能很难深入,在这里你可以找到要运行的整个代码。
1.通过any combination of arguments
澄清:我应该能够给予任何参数,我想手动设置(以秩序与一些失踪)和其余的回退到默认值
2条答案
按热度按时间lmvvr0a81#
这里的主要问题是,你的构造函数的 * 实现 * 将是疯狂的,因为它会搜索正确类型的属性的输入。它本质上要求没有两个参数是相同的类型,因为否则会有歧义.对于编写的代码,实现可能类似于
字符串
它应该能正常工作,但它太脆弱了。
无论如何,假设你确实想要这样一个实现,仍然存在如何输入的问题。你说输入必须是
videoPlayer: HTMLVideoElement, playbackRates: PlaybackRates, options: PlaybackControlOptions
,以便可能缺少一些,所以,例如,如果videoPlayer
和options
都存在,你就不会在videoPlayer
之前传入options
。你可以手动重载构造函数来接受每一个可能的输入组合,但是我喜欢玩类型,所以让我们写一个
Subsequence<T>
实用程序类型,它接受一个输入元组类型T
,并产生T
的每一个可能的subsequence的并集。那么构造函数的输入可以是:
型
这给
型
因此,完整的构造函数看起来像
型
它的行为如你所愿。
型
但是,值得吗?几乎可以肯定不是。疯狂的实现加上疯狂的输入等于太疯狂了。做这样的事情的传统方法是采用类型为
{videoPlayer?: HTMLVideoElement, playbackRates?: PlaybackRates, options?: PlaybackControlOptions}
的单个对象输入,以利用JavaScript中的对象给予您的属性顺序的自然无关性。模糊性消失了(例如,{a?: string, b?: string}
将需要{a: "c"}
或{b: "c"}
,而且打字也很简单。所以你应该这样做。Playground链接到代码
xkftehaa2#
如果我尝试以下操作时失败:
字符串
我不会尝试重载构造函数来接受这个。它需要检查第一个参数是dom元素还是选项对象,然后将参数放入相应的变量中。这会导致相当丑陋的代码和复杂的类型签名。
相反,要跳过传递前两个参数,请为它们传递
undefined
,然后将选项对象作为第三个参数传递:型
如果这是常见用法,请考虑将构造函数更改为仅接受一个对象参数,以便调用
型