Skip to content

Commit 6d9eb1e

Browse files
committed
feat(ts): [NodeErrorConstructor] allow custom util.format args type
- https://nodejs.org/api/util.html#utilformatformat-args Signed-off-by: Lexus Drumgold <[email protected]>
1 parent 292c81e commit 6d9eb1e

File tree

4 files changed

+37
-10
lines changed

4 files changed

+37
-10
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ constructor arguments are passed to [`util.format`][7] instead.
301301

302302
- `{ErrorCode}` **`code`** &mdash; Node.js error code
303303
- `{B extends ErrorConstructor}` **`Base`** &mdash; Error base class
304-
- `{M extends MessageFn | string}` **`message`** &mdash; Error message or message function
304+
- `{M extends any[] | MessageFn | string}` **`message`** &mdash; Error message or message function
305305
- **Returns**: `{NodeErrorConstructor<B, M>}` `NodeError` constructor
306306

307307
> **Source**: [`src/create-node-error.ts`](src/create-node-error.ts)

src/types/__tests__/node-error-constructor.spec-d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ describe('unit-d:types/NodeErrorConstructor', () => {
1212
expectTypeOf<TestSubject>().constructorParameters.toEqualTypeOf<any[]>()
1313
})
1414

15+
it('should extract parameters of type M if M extends any[]', () => {
16+
// Arrange
17+
type B = ErrorConstructor
18+
type M = [string, string, string]
19+
20+
expectTypeOf<TestSubject<B, M>>().parameters.toEqualTypeOf<M>()
21+
expectTypeOf<TestSubject<B, M>>().constructorParameters.toEqualTypeOf<M>()
22+
})
23+
1524
it('should extract parameters of type Parameters<M> if M extends MessageFn', () => {
1625
type B = TypeErrorConstructor
1726
type M = (ext: string, path: string) => string

src/types/node-error-constructor.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,39 @@ import type { Overwrite } from '@flex-development/tutils'
77
import type MessageFn from './fn-message'
88
import type NodeError from './node-error'
99

10+
/**
11+
* {@linkcode NodeErrorConstructor} arguments helper.
12+
*
13+
* [1]: https://nodejs.org/api/util.html#utilformatformat-args
14+
*
15+
* @template M - Error message type, [`util.format`][1] arguments type, or
16+
* custom message function parameters type
17+
*/
18+
type Args<M extends any[] | MessageFn | string> = M extends MessageFn
19+
? Parameters<M>
20+
: M extends any[]
21+
? M
22+
: any[]
23+
1024
/**
1125
* Node.js error constructor type.
1226
*
27+
* [1]: https://nodejs.org/api/util.html#utilformatformat-args
28+
*
1329
* @template B - Error base class type
14-
* @template M - Error message type
30+
* @template M - Error message type, [`util.format`][1] arguments type, or
31+
* custom message function parameters type
1532
* @template T - Error base type
1633
*
1734
* @extends {Overwrite<B, B>}
1835
*/
1936
type NodeErrorConstructor<
2037
B extends ErrorConstructor = ErrorConstructor,
21-
M extends MessageFn | string = string,
38+
M extends any[] | MessageFn | string = MessageFn,
2239
T extends B['prototype'] = B['prototype']
2340
> = Overwrite<B, B> & {
24-
(...args: M extends MessageFn ? Parameters<M> : any[]): NodeError<T>
25-
new (...args: M extends MessageFn ? Parameters<M> : any[]): NodeError<T>
41+
(...args: Args<M>): NodeError<T>
42+
new (...args: Args<M>): NodeError<T>
2643
readonly prototype: NodeError<T>
2744
}
2845

src/utils/create-node-error.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import type { MessageFn, NodeError, NodeErrorConstructor } from '#src/types'
2121
* [2]: https://nodejs.org/api/util.html#utilformatformat-args
2222
*
2323
* @template B - Error base class type
24-
* @template M - Error message type
24+
* @template M - Error message type, [`util.format`][2] arguments type, or
25+
* custom message function parameters type
2526
* @template T - Error base type
2627
*
2728
* @constructs NodeError<T>
@@ -33,7 +34,7 @@ import type { MessageFn, NodeError, NodeErrorConstructor } from '#src/types'
3334
*/
3435
function createNodeError<
3536
B extends ErrorConstructor = ErrorConstructor,
36-
M extends MessageFn | string = MessageFn | string,
37+
M extends any[] | MessageFn | string = MessageFn,
3738
T extends B['prototype'] = B['prototype']
3839
>(code: ErrorCode, Base: B, message: M): NodeErrorConstructor<B, M, T> {
3940
/**
@@ -44,12 +45,12 @@ function createNodeError<
4445
* @class
4546
* @implements {NodeError<T>}
4647
*
47-
* @param {any[] | Parameters<M>} args - `message` params if `message` is a
48-
* function; [`util.format`][1] arguments if `message` is a string
48+
* @param {any[] | M | Parameters<M>} args - `message` params if `message` is
49+
* a function; [`util.format`][1] arguments if `message` is a string
4950
* @return {NodeError<T>} Node.js error instance
5051
*/
5152
function NodeError(
52-
...args: M extends MessageFn ? Parameters<M> : any[]
53+
...args: M extends MessageFn ? Parameters<M> : M extends any[] ? M : any[]
5354
): NodeError<T> {
5455
/**
5556
* Node.js error instance.

0 commit comments

Comments
 (0)