Skip to content

Commit

Permalink
fix: support multiple positionals in polymorphic errors (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito authored Jul 5, 2024
1 parent ec3cd3c commit ccbc6d8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 13 deletions.
33 changes: 25 additions & 8 deletions src/invariant.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,32 @@ it('throws an exception if the predicate is falsy', () => {
}).toThrow(new InvariantError('Error message'))

expect(() => invariant(null, 'Error message')).toThrow(
new InvariantError('Error message')
new InvariantError('Error message'),
)
expect(() => invariant(undefined, 'Error message')).toThrow(
new InvariantError('Error message')
new InvariantError('Error message'),
)
})

it('supports positional values in the error message', () => {
// Strings.
expect(() => invariant(false, 'Cannot %s the %s', 'fetch', 'user')).toThrow(
new InvariantError('Cannot fetch the user')
new InvariantError('Cannot fetch the user'),
)

// Numbers.
expect(() => invariant(false, 'Expected %d apples', 3)).toThrow(
new InvariantError('Expected 3 apples')
new InvariantError('Expected 3 apples'),
)

// Booleans.
expect(() => invariant(false, 'Expected %s but got %s', true, false)).toThrow(
new InvariantError('Expected true but got false')
new InvariantError('Expected true but got false'),
)

// Objects.
expect(() =>
invariant(false, 'Cannot create user: %o', { name: 'John' })
invariant(false, 'Cannot create user: %o', { name: 'John' }),
).toThrow(new InvariantError(`Cannot create user: {"name":"John"}`))
})

Expand Down Expand Up @@ -69,7 +69,7 @@ it('supports polymorphic error class with additional arguments', () => {
class NetworkError extends Error {
constructor(
public readonly errorCode: number,
public readonly message: string
public readonly message: string,
) {
super(message)
Object.setPrototypeOf(this, NetworkError.prototype)
Expand All @@ -81,11 +81,28 @@ it('supports polymorphic error class with additional arguments', () => {
(message) => new NetworkError(230, message),
false,
'Failed to handle %s',
'http://localhost:3000'
'http://localhost:3000',
)
} catch (error) {
expect(error).toBeInstanceOf(NetworkError)
expect(error).toBeInstanceOf(Error)
expect(error.message).toEqual('Failed to handle http://localhost:3000')
}
})

it('supports polymorphic error class with multiple positionals', () => {
class MyError extends Error {
constructor(message?: string) {
super(message)
Object.setPrototypeOf(this, MyError.prototype)
}
}

try {
invariant.as(MyError, false, 'Cannot %s the %s', 'fetch', 'user')
} catch (error) {
expect(error).toBeInstanceOf(MyError)
expect(error).toBeInstanceOf(Error)
expect(error.message).toBe('Cannot fetch the user')
}
})
13 changes: 8 additions & 5 deletions src/invariant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,16 @@ export const invariant: Invariant = (

invariant.as = (ErrorConstructor, predicate, message, ...positionals) => {
if (!predicate) {
const formatMessage = positionals.length === 0 ? message : format(message, positionals);
let error: Error;
const formatMessage =
positionals.length === 0 ? message : format(message, ...positionals)
let error: Error

try {
error = Reflect.construct(ErrorConstructor as CustomErrorConstructor, [formatMessage]);
} catch(err) {
error = (ErrorConstructor as CustomErrorFactory)(formatMessage);
error = Reflect.construct(ErrorConstructor as CustomErrorConstructor, [
formatMessage,
])
} catch (err) {
error = (ErrorConstructor as CustomErrorFactory)(formatMessage)
}

throw error
Expand Down

0 comments on commit ccbc6d8

Please sign in to comment.