A mapped type can mark every property readonly for immutable snapshots.

Readonly Snapshot Shape

readonly_snapshot.ts
type Counter = {
    count: number;
    label: string;
};

type Snapshot<T> = {
    readonly [K in keyof T]: T[K];
};

function describeSnapshot(snapshot: Snapshot<Counter>): string {
    return `${snapshot.label}=${snapshot.count}`;
}

const countValue: number = ;
const snapshot: Snapshot<Counter> = {
    count: countValue,
    label: "runs",
};

console.log(describeSnapshot(snapshot));
type Counter = {
    count: number;
    label: string;
};

type Snapshot<T> = {
    readonly [K in keyof T]: T[K];
};

function describeSnapshot(snapshot: Snapshot<Counter>): string {
    return `${snapshot.label}=${snapshot.count}`;
}

const countValue: number = ;
const snapshot: Snapshot<Counter> = {
    count: countValue,
    label: "runs",
};

console.log(describeSnapshot(snapshot));
readonly mapped property Adding `readonly` inside a mapped type creates a version whose properties cannot be reassigned.