kakasoo / kakasoo/DeepStrictTypes
[BUG] `readonly` array modifier lost during type transformation
- Dominant language
- TypeScript
- Stars
- 64
- Forks
- 2
- PR merge metrics
- No merged PRs in 30d
Description
# Bug Report
**Description**
In `DeepDateToString`, `DeepStrictMerge`, `DeepMerge`, and `DeepStrictUnbrand`, when a `readonly` array is provided as input, the `readonly` modifier is lost in the output type. Since type safety is the core focus of this library, loss of modifier information is a bug.
**Type Issue Example**
When a `readonly` array is provided as input, the output is converted to a mutable `Array`.
**Type Input**
```typescript
// === DeepDateToString ===
type Input1 = readonly { date: Date }[];
type Result1 = DeepDateToString;
// Expected: readonly { date: string }[]
// Actual: { date: string }[] (readonly lost)
// === DeepStrictMerge ===
type Target = readonly { a: number }[];
type Source = readonly { b: string }[];
type Result2 = DeepStrictMerge;
// Expected: readonly { a: number; b: string }[]
// Actual: { a: number; b: string }[] (readonly lost)
// === DeepStrictUnbrand ===
type Input3 = readonly { a: number & { __brand: 'ID' } }[];
type Result3 = DeepStrictUnbrand;
// Expected: readonly { a: number }[]
// Actual: { a: number }[] (readonly lost)
```
**Affected Files**
| File | Line | Issue |
|------|------|-------|
| `src/types/DeepDateToString.ts` | 29-30 | Only matches `Array`, no `readonly` array branch |
| `src/types/DeepStrictMerge.ts` | 13-15 | Only matches `Array`, no `readonly` array branch |
| `src/types/DeepMerge.ts` | 66-73 | Same pattern |
| `src/types/DeepStrictUnbrand.ts` | 56-68 | Only matches `Array`, no `readonly` array branch |
**Fix**
Add a `readonly (infer I)[]` branch after each `Array` branch to handle `readonly` arrays separately. This pattern is already used in `DeepStrictObjectKeys`:
```typescript
// DeepStrictObjectKeys.ts:109 (existing reference pattern)
: DeepStrictUnbrand extends readonly (infer Element)[]
```
**Test Requirements**
All changes must include the following tests:
1. **Backward Compatibility**
- All existing mutable array tests must pass (`npm run build:test && npm run test`)
- Add tests to verify that existing type behavior remains unchanged
2. **Fix Verification**
- For each type, verify `readonly` is preserved when inputting a `readonly` array using the `Equal` pattern
3. **Complex Type Stability**
- `readonly { nested: { deep: Date } }[]` (readonly + nesting + Date)
- `readonly [{ a: 1 }, { b: 2 }]` (readonly tuple)
- `readonly { a: number & MinLength<1> }[]` (readonly + branded)
- `readonly (readonly { a: 1 }[])[]` (2D readonly array)
- `readonly { items: readonly { date: Date }[] }[]` (nested readonly arrays)
**How to verify:**
```bash
npm run build:test && npm run test
npm run prettier
```
Contributor guide
Research direction
Start with the affected branches in src/types/DeepDateToString.ts, src/types/DeepStrictMerge.ts, src/types/DeepMerge.ts, and src/types/DeepStrictUnbrand.ts, using the readonly-array pattern in DeepStrictObjectKeys.ts as a reference. Add coverage for the listed readonly arrays, tuples, nesting, and branded types using Equal. Run npm run build:test && npm run test, then npm run prettier; done means readonly modifiers and existing mutable-array behavior are preserved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100