8000 Update types to support union-type arguments · demurgos/plugin-error@63a2f45 · GitHub
[go: up one dir, main page]

Skip to content

Commit 63a2f45

Browse files
committed
Update types to support union-type arguments
This commit updates the signature of the `PluginError` constructor to loosen the constraints on the parameters in order to support union types while keeping inference on custom properties. This allows for example to use the pattern below: ``` function createPluginError(error: Error | string) { return new PluginError("test", error); } ``` (The tests were updated with more complex cases) See the discussions in gulpjs#10 and gulpjs#11 for details. - Closes gulpjs#10 - Closes gulpjs#11 /cc @gucong3000
1 parent 4dfcef3 commit 63a2f45

File tree

2 files changed

+101
-14
lines changed

2 files changed

+101
-14
lines changed

index.d.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
declare namespace PluginError {
2-
export interface Constructor {
2+
interface Constructor {
33
/**
4-
* @param options Options with plugin name and message
4+
* @param plugin Plugin name
5+
* @param error Base error
6+
* @param options Error options
57
*/
6-
new(options: Options & {plugin: string, message: string}): PluginError;
8+
new <E extends Error>(plugin: string, error: E, options?: Options): PluginError<E>;
79

810
/**
911
* @param plugin Plugin name
10-
* @param message Error message
12+
* @param error Base error or error message
1113
* @param options Error options
1214
*/
13-
new (plugin: string, message: string, options?: Options): PluginError;
15+
new <E extends Error = Error>(plugin: string, error: E | string, options: Options): PluginError<E | {[K in keyof E]: undefined}>;
1416

1517
/**
1618
* @param plugin Plugin name
17-
* @param error Base error
18-
* @param options Error options
19+
* @param error Base error, error message, or options with message
1920
*/
20-
new <E extends Error>(plugin: string, error: E, options?: Options): PluginError<E>;
21+
new <E extends Error = Error>(plugin: string, error: E | string | (Options & {message: string})): PluginError<E | {[K in keyof E]: undefined}>;
2122

2223
/**
23-
* @param plugin Plugin name
24-
* @param options Options with message
24+
* @param options Options with plugin name and message
2525
*/
26-
new(plugin: string, options: Options & {message: string}): PluginError;
26+
new(options: Options & {plugin: string, message: string}): PluginError;
2727
}
2828

2929
interface Options {
@@ -74,8 +74,10 @@ declare namespace PluginError {
7474

7575
/**
7676
* The `Base` interface defines the properties available on all the the instances of `PluginError`.
77+
*
78+
* @internal
7779
*/
78-
export interface Base extends Error {
80+
interface SimplePluginError extends Error {
7981
/**
8082
* Plugin name
8183
*/
@@ -106,7 +108,7 @@ declare namespace PluginError {
106108
/**
107109
* Abstraction for error handling for Vinyl plugins
108110
*/
109-
type PluginError<T = {}> = PluginError.Base & T;
111+
type PluginError<T = {}> = PluginError.SimplePluginError & T;
110112

111113
declare const PluginError: PluginError.Constructor;
112114

test/types/test.ts

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import PluginError = require("plugin-error");
2626

2727
{
2828
const existingError = new Error("OMG");
29-
const err = new PluginError("test", existingError, {showStack: true});
29+
const options: PluginError.Options = {showStack: true};
30+
const err = new PluginError("test", existingError, options);
3031
}
3132
}
3233

@@ -51,3 +52,87 @@ import PluginError = require("plugin-error");
5152
}
5253
}
5354

55+
{
56+
// Union types
57+
const PLUGIN_NAME: string = "test";
58+
59+
interface FooError extends Error {
60+
foo: number;
61+
}
62+
63+
const ERROR: Error = new Error("something broke");
64+
const FOO_ERROR: FooError = Object.assign(new Error("something broke"), {foo: 1});
65+
const MESSAGE: string = "something broke";
66+
const OPTIONS: {message: string} = {message: "something broke"};
67+
68+
{
69+
function createError(error: Error | string) {
70+
return new PluginError(PLUGIN_NAME, error);
71+
}
72+
const pluginError1 = createError(ERROR);
73+
const pluginError2 = createError(FOO_ERROR);
74+
const pluginError3 = createError(MESSAGE);
75+
// The following code should cause a compilation error:
76+
// const foo: any = pluginError2.foo;
77+
}
78+
79+
{
80+
// Make sure that custom properties are preserved
81+
function createError(error: FooError) {
82+
return new PluginError(PLUGIN_NAME, error);
83+
}
84+
const pluginError = createError(FOO_ERROR);
85+
const foo: number = pluginError.foo;
86+
}
87+
88+
{
89+
// Just check that there's no issue when building it with a string
90+
function createError(error: string) {
91+
return new PluginError(PLUGIN_NAME, error);
92+
}
93+
const pluginError = createError(MESSAGE);
94+
// The following code should cause a compilation error:
95+
// const foo: any = pluginError.foo;
96+
}
97+
98+
{
99+
// Check that custom properties are preserved but marked as potentially missing
100+
// The `foo` property must be of type `number | undefined` because it's existence depends
101+
// on the way `createError` is called.
102+
function createError(error: FooError | string) {
103+
return new PluginError(PLUGIN_NAME, error);
104+
}
105+
106+
const pluginError1 = createError(FOO_ERROR);
107+
const foo1: number | undefined = pluginError1.foo;
108+
// The following code should cause a compilation error:
109+
// const foo2: number = pluginError1.foo;
110+
111+
const pluginError2 = createError(MESSAGE);
112+
const foo3: number | undefined = pluginError2.foo;
113+
// The following code should cause a compilation error:
114+
// const foo4: number = pluginError2.foo;
115+
}
116+
117+
{
118+
// Check support for unions with option object
119+
function createError(error: FooError | string | (PluginError.Options & {message: string})) {
120+
return new PluginError(PLUGIN_NAME, error);
121+
}
122+
123+
const pluginError1 = createError(FOO_ERROR);
124+
const foo1: number | undefined = pluginError1.foo;
125+
// The following code should cause a compilation error:
126+
// const foo2: number = pluginError1.foo;
127+
128+
const pluginError2 = createError(MESSAGE);
129+
const foo3: number | undefined = pluginError2.foo;
130+
// The following code should cause a compilation error:
131+
// const foo4: number = pluginError2.foo;
132+
133+
const pluginError3 = createError(MESSAGE);
134+
const foo5: number | undefined = pluginError3.foo;
135+
// The following code should cause a compilation error:
136+
// const foo6: number = pluginError3.foo;
137+
}
138+
}

0 commit comments

Comments
 (0)
0