Skip to content

Improve array function error messages with signatures and examples#35

Merged
Sander-Toonen merged 2 commits intomasterfrom
copilot/improve-error-messaging
Jan 23, 2026
Merged

Improve array function error messages with signatures and examples#35
Sander-Toonen merged 2 commits intomasterfrom
copilot/improve-error-messaging

Conversation

Copy link

Copilot AI commented Jan 23, 2026

Array function errors were technical and unhelpful. Updated to include function signature, received type, and usage example.

Changes

  • Added getTypeName() helper for user-friendly type descriptions
  • Updated error messages for all array functions: filter, map, fold, find, some, every, indexOf, join, sum, count, unique
  • Added 19 test cases for error message validation

Before/After

// Before
"First argument to filter is not a function"

// After
filter(predicate, array) expects a function as first argument, got number.
Example: filter(x => x > 0, [1, -2, 3])
Original prompt

Current errors are technical. Suggest user-friendly alternatives:

// Current:
"First argument to filter is not a function"

// Better:
"filter(predicate, array) expects a function as first argument, got number.
Example: filter(x => x > 0, [1, -2, 3])"


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Updated error messages in src/functions/array/operations.ts to include:
- Function signature information
- The actual type that was received
- Usage examples

Added comprehensive tests for all updated error messages.

Co-authored-by: Sander-Toonen <5106372+Sander-Toonen@users.noreply.github.com>
Copilot AI changed the title [WIP] Update error messages for user-friendliness Improve array function error messages with signatures and examples Jan 23, 2026
Copilot AI requested a review from Sander-Toonen January 23, 2026 18:51
@Sander-Toonen Sander-Toonen marked this pull request as ready for review January 23, 2026 18:53
Copilot AI review requested due to automatic review settings January 23, 2026 18:53
@Sander-Toonen Sander-Toonen merged commit c09c377 into master Jan 23, 2026
8 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes array function argument errors more user-friendly by including the function signature, the received argument type, and a usage example, and adds tests to validate the new messages.

Changes:

  • Added a getTypeName() helper to produce readable runtime type names (null, array, string, etc.).
  • Updated thrown error messages in array operations to include signature + expected type + received type + example.
  • Added a dedicated test suite validating the new error messages for array functions.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 10 comments.

File Description
src/functions/array/operations.ts Adds getTypeName() and updates argument-type errors for array operation functions to include signatures and examples.
test/functions/functions-array-errors.ts Adds tests that assert the new error message format (signature/type/example) for array functions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +51 to +56
it('should provide user-friendly error when third argument is not an array', function () {
const parser = new Parser();
expect(() => parser.evaluate('f(a, b) = a + b; fold(f, 0, {a: 1})')).toThrow(
/fold\(reducer, initial, array\) expects an array as third argument, got object/
);
});
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test validates the main part of the fold(...) error, but it doesn’t assert that the message includes the usage Example: line. Since the PR adds examples to these errors, consider asserting Example: is present here too.

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +82
it('should provide user-friendly error when second argument is not an array', function () {
const parser = new Parser();
expect(() => parser.evaluate('f(x) = x > 0; find(f, 99)')).toThrow(
/find\(predicate, array\) expects an array as second argument, got number/
);
});
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test validates the main part of the find(...) error, but it doesn’t assert that the message includes the usage Example: line. Adding an Example: assertion here would better cover the new behavior introduced by this PR.

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +91
describe('some()', function () {
it('should provide user-friendly error when first argument is not a function', function () {
const parser = new Parser();
expect(() => parser.evaluate('some(5, [1, 2, 3])')).toThrow(
/some\(predicate, array\) expects a function as first argument, got number/
);
});
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither of the some(...) error tests asserts that the message contains the Example: line. Since this PR adds examples to these errors, consider asserting Example: is included for both cases to prevent regressions.

Copilot uses AI. Check for mistakes.
Comment on lines +101 to +107
describe('every()', function () {
it('should provide user-friendly error when first argument is not a function', function () {
const parser = new Parser();
expect(() => parser.evaluate('every({a: 1}, [1, 2, 3])')).toThrow(
/every\(predicate, array\) expects a function as first argument, got object/
);
});
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither of the every(...) error tests asserts that the message contains the Example: line. Since this PR adds examples to these errors, consider asserting Example: is included for both cases to prevent regressions.

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +172
it('should provide user-friendly error from unique when argument is not an array', function () {
const parser = new Parser();
expect(() => parser.evaluate('distinct({a: 1})')).toThrow(
/unique\(array\) expects an array as argument, got object/
);
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test currently expects distinct(...) to throw an error message that starts with unique(array) .... Since distinct is user-facing, it would be clearer if the error message used the distinct(array) signature (and included an Example: line) instead of exposing the alias target.

Suggested change
it('should provide user-friendly error from unique when argument is not an array', function () {
const parser = new Parser();
expect(() => parser.evaluate('distinct({a: 1})')).toThrow(
/unique\(array\) expects an array as argument, got object/
);
it('should provide user-friendly error when argument is not an array', function () {
const parser = new Parser();
expect(() => parser.evaluate('distinct({a: 1})')).toThrow(
/distinct\(array\) expects an array as argument, got object/
);
expect(() => parser.evaluate('distinct({a: 1})')).toThrow(/Example:/);

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +63
it('should provide user-friendly error from fold when first argument is not a function', function () {
const parser = new Parser();
expect(() => parser.evaluate('reduce(true, 0, [1, 2, 3])')).toThrow(
/fold\(reducer, initial, array\) expects a function as first argument, got boolean/
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test codifies reduce(...) raising an error message that starts with fold(...). Since reduce is a user-facing function, it would be clearer if the thrown message referenced reduce(reducer, initial, array) (and included a reduce(...) example) rather than leaking the alias implementation detail.

Suggested change
it('should provide user-friendly error from fold when first argument is not a function', function () {
const parser = new Parser();
expect(() => parser.evaluate('reduce(true, 0, [1, 2, 3])')).toThrow(
/fold\(reducer, initial, array\) expects a function as first argument, got boolean/
it('should provide user-friendly error when first argument is not a function', function () {
const parser = new Parser();
expect(() => parser.evaluate('reduce(true, 0, [1, 2, 3])')).toThrow(
/reduce\(reducer, initial, array\) expects a function as first argument, got boolean/

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +13
expect(() => parser.evaluate('filter(42, [1, 2, 3])')).toThrow(
/filter\(predicate, array\) expects a function as first argument, got number/
);
expect(() => parser.evaluate('filter(42, [1, 2, 3])')).toThrow(/Example:/);
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Example: assertion re-evaluates the same expression a second time (which re-parses and re-runs the evaluation). To keep tests faster and avoid any unintended side effects, consider capturing the thrown error once and asserting on its .message for both the main text and the Example: line.

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +44
throw new Error(
`fold(reducer, initial, array) expects a function as first argument, got ${getTypeName(f)}.\n` +
'Example: fold((acc, x) => acc + x, 0, [1, 2, 3])'
);
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reduce() is an alias for fold(), so any argument-type errors triggered via reduce(...) will now surface an error message that starts with fold(reducer, initial, array) .... That’s confusing for users who called reduce. Consider having reduce() do its own argument validation / error formatting (or catch and rethrow) so the message references reduce(reducer, initial, array) and provides a reduce(...) example.

Copilot uses AI. Check for mistakes.
Comment on lines +211 to +214
throw new Error(
`unique(array) expects an array as argument, got ${getTypeName(a)}.\n` +
'Example: unique([1, 2, 2, 3, 3, 3])'
);
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

distinct() is a public alias for unique(), but any argument-type errors triggered via distinct(...) will now mention unique(array) ..., which can be confusing. Consider validating/rethrowing inside distinct() so the message uses the distinct(array) signature (and example) while still delegating the implementation to unique().

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +39
it('should provide user-friendly error when second argument is not an array', function () {
const parser = new Parser();
expect(() => parser.evaluate('f(x) = x * 2; map(f, 123)')).toThrow(
/map\(mapper, array\) expects an array as second argument, got number/
);
});
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test validates the main part of the map(...) error, but it doesn’t assert that the message includes the usage Example: line. Since the PR’s goal is to add signature + example to these errors, consider asserting Example: is present here too to prevent regressions.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants