Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
declare namespace PluginError {
export interface Constructor {
interface Constructor {
/**
* @param options Options with plugin name and message
* @param plugin Plugin name
* @param error Base error
* @param options Error options
*/
new(options: Options & {plugin: string, message: string}): PluginError;
new <E extends Error>(plugin: string, error: E, options?: Options): PluginError<E>;

/**
* @param plugin Plugin name
* @param message Error message
* @param error Base error or error message
* @param options Error options
*/
new (plugin: string, message: string, options?: Options): PluginError;
new <E extends Error = Error>(plugin: string, error: E | string, options: Options): PluginError<E | {[K in keyof E]: undefined}>;

/**
* @param plugin Plugin name
* @param error Base error
* @param options Error options
* @param error Base error, error message, or options with message
*/
new <E extends Error>(plugin: string, error: E, options?: Options): PluginError<E>;
new <E extends Error = Error>(plugin: string, error: E | string | (Options & {message: string})): PluginError<E | {[K in keyof E]: undefined}>;

/**
* @param plugin Plugin name
* @param options Options with message
* @param options Options with plugin name and message
*/
new(plugin: string, options: Options & {message: string}): PluginError;
new(options: Options & {plugin: string, message: string}): PluginError;
}

interface Options {
Expand Down Expand Up @@ -71,11 +71,12 @@ declare namespace PluginError {
stack?: string;
}


/**
* The `Base` interface defines the properties available on all the the instances of `PluginError`.
* The `SimplePluginError` interface defines the properties available on all the the instances of `PluginError`.
*
* @internal
*/
export interface Base extends Error {
interface SimplePluginError extends Error {
/**
* Plugin name
*/
Expand Down Expand Up @@ -106,7 +107,7 @@ declare namespace PluginError {
/**
* Abstraction for error handling for Vinyl plugins
*/
type PluginError<T = {}> = PluginError.Base & T;
type PluginError<T = {}> = PluginError.SimplePluginError & T;

declare const PluginError: PluginError.Constructor;

Expand Down
87 changes: 86 additions & 1 deletion test/types/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import PluginError = require("plugin-error");

{
const existingError = new Error("OMG");
const err = new PluginError("test", existingError, {showStack: true});
const options: PluginError.Options = {showStack: true};
const err = new PluginError("test", existingError, options);
}
}

Expand All @@ -51,3 +52,87 @@ import PluginError = require("plugin-error");
}
}

{
// Union types
const PLUGIN_NAME: string = "test";

interface FooError extends Error {
foo: number;
}

const ERROR: Error = new Error("something broke");
const FOO_ERROR: FooError = Object.assign(new Error("something broke"), {foo: 1});
const MESSAGE: string = "something broke";
const OPTIONS: {message: string} = {message: "something broke"};

{
function createError(error: Error | string) {
return new PluginError(PLUGIN_NAME, error);
}
const pluginError1 = createError(ERROR);
const pluginError2 = createError(FOO_ERROR);
const pluginError3 = createError(MESSAGE);
// The following code should cause a compilation error:
// const foo: any = pluginError2.foo;
}

{
// Make sure that custom properties are preserved
function createError(error: FooError) {
return new PluginError(PLUGIN_NAME, error);
}
const pluginError = createError(FOO_ERROR);
const foo: number = pluginError.foo;
}

{
// Just check that there's no issue when building it with a string
function createError(error: string) {
return new PluginError(PLUGIN_NAME, error);
}
const pluginError = createError(MESSAGE);
// The following code should cause a compilation error:
// const foo: any = pluginError.foo;
}

{
// Check that custom properties are preserved but marked as potentially missing
// The `foo` property must be of type `number | undefined` because it's existence depends
// on the way `createError` is called.
function createError(error: FooError | string) {
return new PluginError(PLUGIN_NAME, error);
}

const pluginError1 = createError(FOO_ERROR);
const foo1: number | undefined = pluginError1.foo;
// The following code should cause a compilation error:
// const foo2: number = pluginError1.foo;

const pluginError2 = createError(MESSAGE);
const foo3: number | undefined = pluginError2.foo;
// The following code should cause a compilation error:
// const foo4: number = pluginError2.foo;
}

{
// Check support for unions with option object
function createError(error: FooError | string | (PluginError.Options & {message: string})) {
return new PluginError(PLUGIN_NAME, error);
}

const pluginError1 = createError(FOO_ERROR);
const foo1: number | undefined = pluginError1.foo;
// The following code should cause a compilation error:
// const foo2: number = pluginError1.foo;

const pluginError2 = createError(MESSAGE);
const foo3: number | undefined = pluginError2.foo;
// The following code should cause a compilation error:
// const foo4: number = pluginError2.foo;

const pluginError3 = createError(OPTIONS);
const foo5: number | undefined = pluginError3.foo;
// The following code should cause a compilation error:
// const foo6: number = pluginError3.foo;
}
}