Poznajemy utility type TypeScripta Readonly, piszemy go sami plus piszemy sobie własny utility type o nazwie Writable, który robi coś odwrotnego. Zaczynajmy.

Ok, poznajmy readonly:

interface Todo {
  title: string;
}
 
const todo: Readonly<Todo> = {
  title: "Delete inactive users",
};
 
todo.title = "Hello";
Cannot assign to 'title' because it is a read-only property.

Piszą też, że jak chcemy robić freeze to taki typ powinniśmy zwracać:

function freeze<Type>(obj: Type): Readonly<Type>;

Ma to sens, dzięki temu to co w runtime i to co w compile time będą się odzwierciedlać. Ok, napiszmy własny readonly:

type ReadOnly2<T> = {
    readonly [P in keyof T]: T[P];
};

Jak widać dodajmy readonly keyword do wszystkich pól. Zobaczmy jak działa:

interface Employee2 {
    id: number;
    name: string;
    age: number;
    salary: number;
}

type ReadOnly2<T> = {
    readonly [P in keyof T]: T[P];
};

type ReadonlyEmp = ReadOnly2<Employee2>

// type ReadonlyEmp = {
//     readonly id: number;
//     readonly name: string;
//     readonly age: number;
//     readonly salary: number;
// }

Ok, napiszemy sobie teraz Writable<T>:

type Writable<T> = {
    -readonly[P in keyof T]: T[P];
}

Tu jak widać minusikiem zdejmujemy readonly a resztę zostawiamy, jak była. Zobaczmy, jaki tego efekt:

interface ReadOnlyPerson {
    readonly name: string;
    readonly age: number;
    fullname: string;
}

type Writable<T> = {
    -readonly[P in keyof T]: T[P];
}

type example = Writable<ReadOnlyPerson>


// type example = {
//     name: string;
//     age: number;
//     fullname: string;
// }

Ok, więcej TSa niedługo!