blakeembrey / blakeembrey/change-case

change-case/keys fails on Date objects

Open
#356 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2.4k
Forks
106
PR merge metrics
No merged PRs in 30d

Description

Hello 👋

Many thanks for your work on this project. I was hoping to use `change-case/keys` to automatically process database responses (in `snake_case` format) to `camelCase`.

Seeing as this is a global configuration option I wanted to use the `depth` option to work for either a single object returned from the database or an array of objects. However, when parsing a single object that contains a `Date` it looks like the `Date` is not passed through as a value. I have a minimal reproduction here:

```javascript
import { camelCase } from 'change-case/keys';
import { describe, it, expect } from 'vitest';

describe('change-case', () => {
it('should work with date objects', () => {
const originalInput = {date_time: new Date()};

const transformed = camelCase(originalInput, 2);

expect(() => transformed.dateTime.toISOString()).not.toThrowError();
});
});
```

This produces the following exception:

```

FAIL index.test.js > change-case > should work with date objects
AssertionError: expected [Function] to not throw an error but 'TypeError: Method Date.prototype.toIS…' was thrown

- Expected:
undefined

+ Received:
"TypeError: Method Date.prototype.toISOString called on incompatible receiver [object Object]"

❯ index.test.js:10:62
8| const transformed = camelCase(originalInput, 2);
9|
10| expect(() => transformed.dateTime.toISOString()).not.toThr…
| ^
11| })
12| })

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯
```

I got this output from doing `console.log` on both objects:

```
{ date_time: 2025-01-31T12:45:08.814Z }
{ dateTime: Date {} }
```

I would imagine an easy fix would be to ignore `Date` in https://github.com/blakeembrey/change-case/blob/38e6b4f9115cf93b18ca9b1b4a620a32751499cb/packages/change-case/src/keys.ts#L16 - e.g:

```javascript
if (depth === 0 || !isObject(object) || object instanceof Date) return object;
```

However it might be nicer to check if the object is a "plain object" which should cover more cases - for example https://www.npmjs.com/package/is-plain-object

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with packages/change-case/src/keys.ts at the referenced recursion guard and run the provided Vitest reproduction for a Date-valued property. Check how Date objects are handled when depth is 2, then add or update a focused regression test. Done means the transformed date remains usable with toISOString() while existing key conversion behavior still passes.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.