У меня возникли проблемы с потоком с проверкой типов пользовательского типа объединения, который позволяет Function
, Promise
или Array
содержать либо false
, либо экземпляр класса Plugin
.
Код работает без проверки типов и позволяет разработчику вкладывать Plugin
или false
в любой другой разрешенный тип, однако я не могу заставить систему типов разрешать код без каких-либо ошибок.
Я работаю с предположением, что мы можем использовать рекурсивные типы, например type T = false | Array<T>
, поэтому тип может быть либо ложным, либо массивом, содержащим другой тип T
. Я прочитал в комментарии github, что рекурсивные типы или разрешены, однако не смог найти пример кода.
// @flow
type object = {}
type Plugins =
false
| Plugin
| () => Plugins
| Array<Plugins>
| Promise<Plugins>
class Plugin {
name: string
constructor(name) {
this.name = name
}
}
class Engine {
params = {}
plugins = {}
constructor(params: object) {
this.params = params
}
pipe(plugin: Plugins): Engine {
// do nothing if plugins is false
if (plugin === false) {
return this
}
else if (typeof plugin === 'function') {
this.pipe(plugin())
}
// get plugin from inside a Promise
else if (plugin instanceof Promise) {
plugin.then(plugin => this.pipe(plugin))
}
// iterate over each item of an array
else if (Array.isArray(plugin)) {
plugin.forEach(plugin => this.pipe(plugin))
}
// initialize each plugin
else if (plugin instanceof Plugin) {
this.plugins[plugin.name] = plugin
}
// return this for chaining
return this
}
}
const engine = new Engine({ name: 'one'})
.pipe(new Plugin('plugin-one'))
.pipe([new Plugin('plugin-two')])
.pipe(Promise.resolve([new Plugin('plugin-three')]))
.pipe(() => new Plugin('plugin-four'))
// should cause a flow type error
.pipe(true)
// I would like this to work deeply nested in any acceptable type
.pipe([() => Promise.resolve([() => [Promise.resolve([new Plugin('plugin-five')])]])])
setTimeout(function() {
console.log(engine)
}, 20)
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js"></script>
Я пробовал несколько разных определений типов с разной степенью успеха, однако они обычно исправляют предупреждения, но больше не обнаруживают ошибки типа.
Это попытка отделить окончательный тип от типов оболочки
type PluginTypes = false | Plugin
type Plugins =
Array<PluginTypes>
| Promise<PluginTypes>
| () => PluginTypes
Это предотвратит ошибки, добавив Plugins
к типу объединения, однако проверка типов больше не работает.
type Plugins =
false
| Plugin
| Plugins
| Array<Plugins>
| Promise<Plugins>
| () => Plugins
Спасибо за любую помощь