Immer modifies `readonly` properties of nested instances that are not immerable

Ouverte
#1,148 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 4 jours

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
35/100
Type d'issue
Bug
Clarté
À clarifier
Activité
À l'abandon
Stack technique
javascript, typescript
Domaine
tooling

Piste de recherche

Commencez par la reproduction CodeSandbox liée et examinez la gestion existante des instances de classes non immerable et du typage readonly. C'est terminé lorsque le cas Address imbriqué est rejeté de manière cohérente, avec une couverture de régression pour le comportement à l'exécution et/ou le comportement des types ; l'issue ne choisit pas entre ces résultats.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

🐛 Bug Report

immer allows modification of readonly properties of nested class instances that are not marked as immerable. This seems dangerous to me. Just like immer does not allow direct modification of class instances that are not marked as immerable, an exception should be thrown. Even better, the types should not allow this.

import { immerable, produce } from "immer";

class Address {
  constructor(public readonly streetName: string) {
    this.streetName = streetName;
  }
}

class ImmerableAddress {
  [immerable] = true;

  constructor(public readonly streetName: string) {
    this.streetName = streetName;
  }
}

class ImmerablePerson {
  [immerable] = true;

  constructor(public readonly address: Address) {
    this.address = address;
  }
}

describe("immer", () => {
  const immerableAddress = new ImmerableAddress("foo");
  it("works fine with immerable nested class instance", () => {
    const produced = produce(new ImmerablePerson(immerableAddress), (draft) => {
      draft.address.streetName = "bar";
    });
    expect(produced.address.streetName).toBe("bar");
    expect(produced.address).toBeInstanceOf(ImmerableAddress);
    expect(produced.address).not.toBe(immerableAddress);
  });

  const address = new Address("foo");
  it("allows illegal modification of non-immerable nested class instance", () => {
    const produced = produce(new ImmerablePerson(address), (draft) => {
      draft.address.streetName = "bar"; // works unexpectedly
    });
    expect(produced.address.streetName).toBe("bar");
    expect(produced.address).toBeInstanceOf(Address);
    expect(produced.address).toBe(address);
  });
});

Link to repro

CodeSandbox demo

Environment

Immer 10.1.1

Langage dominant
JavaScript
Étoiles
29k
Forks
905
Merge moyen
3 j 16 h
PR mergées (30 j)
22

Préparer son environnement

Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de immerjs/immer

Toutes les issues de immerjs/immer

Issues similaires

Plus d'issues JavaScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.