Skip to content

Commit ccbc6d8

Browse files
authored
fix: support multiple positionals in polymorphic errors (#15)
1 parent ec3cd3c commit ccbc6d8

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

src/invariant.test.ts

+25-8
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,32 @@ it('throws an exception if the predicate is falsy', () => {
1515
}).toThrow(new InvariantError('Error message'))
1616

1717
expect(() => invariant(null, 'Error message')).toThrow(
18-
new InvariantError('Error message')
18+
new InvariantError('Error message'),
1919
)
2020
expect(() => invariant(undefined, 'Error message')).toThrow(
21-
new InvariantError('Error message')
21+
new InvariantError('Error message'),
2222
)
2323
})
2424

2525
it('supports positional values in the error message', () => {
2626
// Strings.
2727
expect(() => invariant(false, 'Cannot %s the %s', 'fetch', 'user')).toThrow(
28-
new InvariantError('Cannot fetch the user')
28+
new InvariantError('Cannot fetch the user'),
2929
)
3030

3131
// Numbers.
3232
expect(() => invariant(false, 'Expected %d apples', 3)).toThrow(
33-
new InvariantError('Expected 3 apples')
33+
new InvariantError('Expected 3 apples'),
3434
)
3535

3636
// Booleans.
3737
expect(() => invariant(false, 'Expected %s but got %s', true, false)).toThrow(
38-
new InvariantError('Expected true but got false')
38+
new InvariantError('Expected true but got false'),
3939
)
4040

4141
// Objects.
4242
expect(() =>
43-
invariant(false, 'Cannot create user: %o', { name: 'John' })
43+
invariant(false, 'Cannot create user: %o', { name: 'John' }),
4444
).toThrow(new InvariantError(`Cannot create user: {"name":"John"}`))
4545
})
4646

@@ -69,7 +69,7 @@ it('supports polymorphic error class with additional arguments', () => {
6969
class NetworkError extends Error {
7070
constructor(
7171
public readonly errorCode: number,
72-
public readonly message: string
72+
public readonly message: string,
7373
) {
7474
super(message)
7575
Object.setPrototypeOf(this, NetworkError.prototype)
@@ -81,11 +81,28 @@ it('supports polymorphic error class with additional arguments', () => {
8181
(message) => new NetworkError(230, message),
8282
false,
8383
'Failed to handle %s',
84-
'http://localhost:3000'
84+
'http://localhost:3000',
8585
)
8686
} catch (error) {
8787
expect(error).toBeInstanceOf(NetworkError)
8888
expect(error).toBeInstanceOf(Error)
8989
expect(error.message).toEqual('Failed to handle http://localhost:3000')
9090
}
9191
})
92+
93+
it('supports polymorphic error class with multiple positionals', () => {
94+
class MyError extends Error {
95+
constructor(message?: string) {
96+
super(message)
97+
Object.setPrototypeOf(this, MyError.prototype)
98+
}
99+
}
100+
101+
try {
102+
invariant.as(MyError, false, 'Cannot %s the %s', 'fetch', 'user')
103+
} catch (error) {
104+
expect(error).toBeInstanceOf(MyError)
105+
expect(error).toBeInstanceOf(Error)
106+
expect(error.message).toBe('Cannot fetch the user')
107+
}
108+
})

src/invariant.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,16 @@ export const invariant: Invariant = (
6464

6565
invariant.as = (ErrorConstructor, predicate, message, ...positionals) => {
6666
if (!predicate) {
67-
const formatMessage = positionals.length === 0 ? message : format(message, positionals);
68-
let error: Error;
67+
const formatMessage =
68+
positionals.length === 0 ? message : format(message, ...positionals)
69+
let error: Error
6970

7071
try {
71-
error = Reflect.construct(ErrorConstructor as CustomErrorConstructor, [formatMessage]);
72-
} catch(err) {
73-
error = (ErrorConstructor as CustomErrorFactory)(formatMessage);
72+
error = Reflect.construct(ErrorConstructor as CustomErrorConstructor, [
73+
formatMessage,
74+
])
75+
} catch (err) {
76+
error = (ErrorConstructor as CustomErrorFactory)(formatMessage)
7477
}
7578

7679
throw error

0 commit comments

Comments
 (0)