Skip to content

Commit eae2f4c

Browse files
authored
Fix: Update types to support union-type arguments (Fixes#10)
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 is a semver minor update (fix). 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 #10 and #11 for details. - Closes#10 - Closes#11 /cc @gucong3000
1 parent 4dfcef3 commit eae2f4c

2 files changed

Lines changed: 102 additions & 16 deletions

File tree

‎index.d.ts‎

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
declarenamespacePluginError{
2-
exportinterfaceConstructor{
2+
interfaceConstructor{
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<EextendsError>(plugin: string,error: E,options?: Options): PluginError<E>;
79

810
/**
911
* @param plugin Plugin name
10-
* @parammessage Error message
12+
* @paramerror Base error or error message
1113
* @param options Error options
1214
*/
13-
new(plugin: string,message: string,options?: Options): PluginError;
15+
new<EextendsError=Error>(plugin: string,error: E|string,options: Options): PluginError<E|{[KinkeyofE]: 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<EextendsError>(plugin: string,error: E,options?: Options): PluginError<E>;
21+
new<EextendsError=Error>(plugin: string,error: E|string|(Options&{message: string})): PluginError<E|{[KinkeyofE]: 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
interfaceOptions{
@@ -71,11 +71,12 @@ declare namespace PluginError {
7171
stack?: string;
7272
}
7373

74-
7574
/**
76-
* The `Base` interface defines the properties available on all the the instances of `PluginError`.
75+
* The `SimplePluginError` interface defines the properties available on all the the instances of `PluginError`.
76+
*
77+
* @internal
7778
*/
78-
exportinterfaceBaseextendsError{
79+
interfaceSimplePluginErrorextendsError{
7980
/**
8081
* Plugin name
8182
*/
@@ -106,7 +107,7 @@ declare namespace PluginError {
106107
/**
107108
* Abstraction for error handling for Vinyl plugins
108109
*/
109-
typePluginError<T={}>=PluginError.Base&T;
110+
typePluginError<T={}>=PluginError.SimplePluginError&T;
110111

111112
declareconstPluginError: PluginError.Constructor;
112113

‎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
constexistingError=newError("OMG");
29-
consterr=newPluginError("test",existingError,{showStack: true});
29+
constoptions: PluginError.Options={showStack: true};
30+
consterr=newPluginError("test",existingError,options);
3031
}
3132
}
3233

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

55+
{
56+
// Union types
57+
constPLUGIN_NAME: string="test";
58+
59+
interfaceFooErrorextendsError{
60+
foo: number;
61+
}
62+
63+
constERROR: Error=newError("something broke");
64+
constFOO_ERROR: FooError=Object.assign(newError("something broke"),{foo: 1});
65+
constMESSAGE: string="something broke";
66+
constOPTIONS: {message: string}={message: "something broke"};
67+
68+
{
69+
functioncreateError(error: Error|string){
70+
returnnewPluginError(PLUGIN_NAME,error);
71+
}
72+
constpluginError1=createError(ERROR);
73+
constpluginError2=createError(FOO_ERROR);
74+
constpluginError3=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+
functioncreateError(error: FooError){
82+
returnnewPluginError(PLUGIN_NAME,error);
83+
}
84+
constpluginError=createError(FOO_ERROR);
85+
constfoo: number=pluginError.foo;
86+
}
87+
88+
{
89+
// Just check that there's no issue when building it with a string
90+
functioncreateError(error: string){
91+
returnnewPluginError(PLUGIN_NAME,error);
92+
}
93+
constpluginError=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+
functioncreateError(error: FooError|string){
103+
returnnewPluginError(PLUGIN_NAME,error);
104+
}
105+
106+
constpluginError1=createError(FOO_ERROR);
107+
constfoo1: number|undefined=pluginError1.foo;
108+
// The following code should cause a compilation error:
109+
// const foo2: number = pluginError1.foo;
110+
111+
constpluginError2=createError(MESSAGE);
112+
constfoo3: 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+
functioncreateError(error: FooError|string|(PluginError.Options&{message: string})){
120+
returnnewPluginError(PLUGIN_NAME,error);
121+
}
122+
123+
constpluginError1=createError(FOO_ERROR);
124+
constfoo1: number|undefined=pluginError1.foo;
125+
// The following code should cause a compilation error:
126+
// const foo2: number = pluginError1.foo;
127+
128+
constpluginError2=createError(MESSAGE);
129+
constfoo3: number|undefined=pluginError2.foo;
130+
// The following code should cause a compilation error:
131+
// const foo4: number = pluginError2.foo;
132+
133+
constpluginError3=createError(OPTIONS);
134+
constfoo5: 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)