Skip to content

Commit

Permalink
Add support for any number of settings in types
Browse files Browse the repository at this point in the history
Closes GH-62.

Reviewed-by: Junyoung Choi <fluke8259@gmail.com>
Reviewed-by: Titus Wormer <tituswormer@gmail.com>
  • Loading branch information
ChristianMurphy authored and wooorm committed Jul 15, 2019
1 parent 8c0285c commit 12865ee
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 41 deletions.
54 changes: 25 additions & 29 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// TypeScript Version: 3.0
// TypeScript Version: 3.4

import {Node} from 'unist'
import {VFile, VFileContents, VFileOptions} from 'vfile'
Expand All @@ -23,33 +23,29 @@ declare namespace unified {
*
* @param plugin unified plugin
* @param settings Configuration for plugin
* @param extraSettings Additional configuration for plugin
* @typeParam S Plugin settings
* @typeParam S2 Extra plugin settings
* @returns The processor on which use is invoked
*/
use<S = Settings, S2 = undefined>(
plugin: Plugin<S, S2, P>,
settings?: S,
extraSettings?: S2
use<S extends any[] = [Settings?]>(
plugin: Plugin<S, P>,
...settings: S
): Processor<P>

/**
* Configure the processor with a preset to use
*
* @param preset `Object` with an plugins (set to list), and/or an optional settings object
*/
use(preset: Preset<P>): Processor<P>
use<S extends any[] = [Settings?]>(preset: Preset<S, P>): Processor<P>

/**
* Configure using a tuple of plugin and setting(s)
*
* @param pluginTuple pairs, plugin and settings in an array
* @typeParam S Plugin settings
* @typeParam S2 Extra plugin settings
*/
use<S = Settings, S2 = Settings>(
pluginTuple: PluginTuple<S, S2, P>
use<S extends any[] = [Settings?]>(
pluginTuple: PluginTuple<S, P>
): Processor<P>

/**
Expand Down Expand Up @@ -214,13 +210,11 @@ declare namespace unified {
*
* @this Processor context object is set to the invoked on processor.
* @param settings Configuration
* @param extraSettings Secondary configuration
* @typeParam S Plugin settings
* @typeParam S2 Extra plugin settings
* @typeParam P Processor settings
* @returns Optional Transformer.
*/
type Plugin<S = Settings, S2 = undefined, P = Settings> = Attacher<S, S2, P>
type Plugin<S extends any[] = [Settings?], P = Settings> = Attacher<S, P>

/**
* Configuration passed to a Plugin or Processor
Expand All @@ -235,7 +229,7 @@ declare namespace unified {
*
* @typeParam P Processor settings
*/
interface Preset<P = Settings> {
interface Preset<S = Settings, P = Settings> {
plugins: PluggableList<P>
settings?: Settings
}
Expand All @@ -253,31 +247,35 @@ declare namespace unified {
* A pairing of a plugin with its settings
*
* @typeParam S Plugin settings
* @typeParam S2 Extra plugin settings
* @typeParam P Processor settings
*/
type PluginTuple<S = Settings, S2 = undefined, P = Settings> =
| [Plugin<S, undefined, P>, S]
| [Plugin<S, S2, P>, S, S2]
type PluginTuple<S extends any[] = [Settings?], P = Settings> = [
Plugin<S, P>,
/**
* NOTE: ideally this would be S instead of any[]
* As of TypeScript 3.5.2 generic tuples cannot be spread
* See: https://github.com/microsoft/TypeScript/issues/26113
*/
...any[]
]

/**
* A union of the different ways to add plugins to unified
*
* @typeParam S Plugin settings
* @typeParam S2 Extra plugin settings
* @typeParam P Processor settings
*/
type Pluggable<S = Settings, S2 = undefined, P = Settings> =
| Plugin<S, S2, P>
| Preset<P>
| PluginTuple<S, S2, P>
type Pluggable<S extends any[] = [Settings?], P = Settings> =
| Plugin<S, P>
| Preset<S, P>
| PluginTuple<S, P>

/**
* A list of plugins and presets
*
* @typeParam P Processor settings
*/
type PluggableList<P = Settings> = Array<Pluggable<any, any, P>>
type PluggableList<P = Settings> = Array<Pluggable<[any?], P>>

/**
* An attacher is the thing passed to `use`.
Expand All @@ -287,14 +285,12 @@ declare namespace unified {
*
* @this Processor context object is set to the invoked on processor.
* @param settings Configuration
* @param extraSettings Secondary configuration
* @typeParam S Plugin settings
* @typeParam S2 Extra plugin settings
* @typeParam P Processor settings
* @returns Optional Transformer.
*/
interface Attacher<S = Settings, S2 = undefined, P = Settings> {
(this: Processor<P>, settings?: S, extraSettings?: S2): Transformer | void
interface Attacher<S extends any[] = [Settings?], P = Settings> {
(this: Processor<P>, ...settings: S): Transformer | void
}

/**
Expand Down
22 changes: 10 additions & 12 deletions types/unified-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const settings = {
interface ExamplePluginSettings {
example: string
}
const typedPlugin: Plugin<ExamplePluginSettings> = function() {}
const typedPlugin: Plugin<[ExamplePluginSettings?]> = function() {}
const typedSetting = {example: 'example'}

const implicitlyTypedPlugin = (settings?: ExamplePluginSettings) => {}
Expand All @@ -51,31 +51,34 @@ processor.use([[plugin, settings], [plugin, settings]])
processor.use(typedPlugin)
processor.use(typedPlugin).use(typedPlugin)
processor.use(typedPlugin, typedSetting)
// NOTE: in tuple/array form settings are not able to be type checked
processor.use([typedPlugin, typedSetting])
processor.use([[typedPlugin, typedSetting], [typedPlugin, typedSetting]])
processor.use([[plugin, settings], [typedPlugin, typedSetting]])
processor.use([typedPlugin])
processor.use([typedPlugin, typedSetting, settings])
processor.use([typedPlugin, settings])

processor.use(implicitlyTypedPlugin)
processor.use(implicitlyTypedPlugin).use(implicitlyTypedPlugin)
processor.use(implicitlyTypedPlugin, typedSetting)
// NOTE: in tuple/array form settings are not able to be type checked
processor.use([implicitlyTypedPlugin, typedSetting])
processor.use([
[implicitlyTypedPlugin, typedSetting],
[implicitlyTypedPlugin, typedSetting]
])
processor.use([[plugin, settings], [implicitlyTypedPlugin, typedSetting]])
processor.use([implicitlyTypedPlugin])

// NOTE: settings overrides the generic undefined
// settings value will be unused but TypeScript will not warn
processor.use(implicitlyTypedPlugin, typedSetting, settings)
processor.use([implicitlyTypedPlugin, settings])
processor.use([implicitlyTypedPlugin, typedSetting, settings])

processor.use(pluginWithTwoSettings)
processor.use(pluginWithTwoSettings).use(pluginWithTwoSettings)
processor.use(pluginWithTwoSettings, processor, typedSetting)
processor.use(pluginWithTwoSettings, processor)
// NOTE: in tuple/array form settings are not able to be type checked
processor.use([pluginWithTwoSettings, processor, settings])
processor.use([pluginWithTwoSettings, processor, typedSetting])
processor.use([pluginWithTwoSettings, processor])
processor.use([
Expand All @@ -91,16 +94,12 @@ processor.use([pluginWithTwoSettings])
// $ExpectError
processor.use(typedPlugin, settings)
// $ExpectError
processor.use([typedPlugin, settings])
// $ExpectError
processor.use(typedPlugin, typedSetting, settings)
// $ExpectError
processor.use([typedPlugin, typedSetting, settings])

// $ExpectError
processor.use(implicitlyTypedPlugin, settings)
// $ExpectError
processor.use([implicitlyTypedPlugin, settings])
processor.use(implicitlyTypedPlugin, typedSetting, settings)

// $ExpectError
processor.use(pluginWithTwoSettings, typedSetting)
Expand All @@ -109,8 +108,6 @@ processor.use(pluginWithTwoSettings, typedSetting)

// $ExpectError
processor.use(pluginWithTwoSettings, processor, settings)
// $ExpectError
processor.use([pluginWithTwoSettings, processor, settings])

// $ExpectError
processor.use({})
Expand Down Expand Up @@ -141,6 +138,7 @@ processor.use({
processor.use({
settings: {}
})

processor.use({
plugins: [plugin]
})
Expand Down

0 comments on commit 12865ee

Please sign in to comment.