kakasoo / kakasoo/DeepStrictTypes
[FEAT] Add `DeepReadonly<T>` type
- Dominant language
- TypeScript
- Stars
- 64
- Forks
- 2
- PR merge metrics
- No merged PRs in 30d
Description
# Feature Request
- [ ] Extensions of existing features
- [x] Propose a type that didn't exist before
**Type Expectation**
A `DeepReadonly` type is needed that recursively converts all properties of objects and arrays to `readonly`. Since this library provides "deep + strict" type manipulation, `DeepReadonly` is a natural extension.
**Example Type**
```typescript
type Input = {
a: number;
b: {
c: string;
d: { e: boolean }[];
};
};
type Result = DeepReadonly;
// Expected:
// {
// readonly a: number;
// readonly b: {
// readonly c: string;
// readonly d: readonly { readonly e: boolean }[];
// };
// }
```
**Proposed Solution**
Create `src/types/DeepReadonly.ts` with the following rules:
1. Add `readonly` modifier to all properties
2. Convert arrays to `readonly T[]`
3. Do not recurse into `Date` types (existing library convention)
4. Preserve branded types (do not unbrand before processing)
5. Add re-export to `src/types/index.ts`
**Use Case**
- Enforce immutability on API response objects to prevent accidental mutation
- Guarantee readonly state in Redux/Zustand store types
- Provide type definitions for the deep version of `Object.freeze`
**Test Requirements**
All changes must include the following tests:
1. **Backward Compatibility**
- All existing tests must pass; the new type must not affect existing types
2. **Feature Verification**
- Simple object readonly conversion
- Nested object readonly conversion
- Array to readonly array
- Objects inside arrays are also readonly
- Date type preserved (not made readonly)
- Already readonly types remain unchanged (idempotency)
3. **Complex Type Stability**
- 3+ levels of nesting (`{ a: { b: { c: { d: number } } } }`)
- 2D arrays (`{ matrix: number[][] }`)
- Arrays inside objects inside arrays (`{ items: { tags: string[] }[] }`)
- Tuple types (`[string, { a: number }]`)
- Optional property preservation (`{ a?: number }` → `{ readonly a?: number }`)
- Union types (`{ a: string | null }`)
- Branded types (`{ id: number & { __brand: 'ID' } }`)
- `any`, `never`, `unknown` properties
**How to verify:**
```bash
npm run build:test && npm run test
npm run prettier
```
Contributor guide
Research direction
Start by reviewing existing deep and strict type utilities, then create src/types/DeepReadonly.ts and inspect src/types/index.ts for the re-export pattern. Add tests for recursive objects, arrays, tuples, dates, branded and edge-case types, then run npm run build:test && npm run test and npm run prettier; done means all listed cases pass without breaking existing tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100