Best way to replace slice mutation

Updating to the TypeScript-based ProseMirror version, I stumbled upon a few plugins in our code base that directly mutate the slices passed in to handlePaste, handleDrop, or transformPasted, for example:

      // Strip out any comments when pasting content
      handlePaste(view, event, slice) {
        slice.content.descendants(node => {
          node.marks = node.marks.filter(isCommentMark);

        return false;


    // Strip out diff marks when pasting content
    transformPasted(slice) {
      slice.content.descendants(node => {
        node.marks = node.marks.filter(isDiffMark);
        if (supportsDiff(node.type)) {
          node.attrs = {
            deleted: false,
            inserted: false,
            modified: false,

      return slice;

That always worked as far as I know, but the new typings have properties such as attrs and marks flagged as readonly. Which makes sense, but now I am struggling to find a good way to create a new slice from a given slice, potentially changing any of the descendants in the slice.

Does someone have an example for how that is best done in an immutable way?

Creating a copy of a node with different marks is done with node.mark. Updating the content of a slice can be done by creating a new slice with an updated fragment.

Ok, node.mark is a nice one that I hadn’t known so far, thanks!

My challenge is then more with recursively replacing node content in the document. I have now put together the following code, does that look like the way to go?

export default new Plugin({
  props: {
    transformPasted(slice) {
      return new Slice(stripDiffFromFragment(slice.content), slice.openStart, slice.openEnd);

function stripDiffFromFragment(fragment: Fragment): Fragment {
  const newNodes: Node[] = [];
  fragment.forEach(node => newNodes.push(stripDiffFromNode(node)));
  return Fragment.fromArray(newNodes);

function stripDiffFromNode(node: Node): Node {
  const newAttrs = supportsDiff(node.type)
    ? {...node.attrs, deleted: false, inserted: false, modified: false}
    : node.attrs;
  const newMarks = node.marks.filter(isDiffMark);
  return schema.node(node.type, newAttrs, stripDiffFromFragment(node.content), newMarks);