Quick Overview
`Partial<T>` makes every property optional, `Pick` keeps named keys and `Omit` drops them. Deriving these from one source type is what stops an update payload drifting from the entity it updates.
### 1. Standard Type Transformations TypeScript provides built-in global **Utility Types** to perform common object shape transformations without manual duplicate type declarations. ### 2. Partial<T> & Required<T> - **`Partial<T>`**: Makes all properties in `T` optional (useful for update payload parameters). - **`Required<T>`**: Makes all properties in `T` required (removes `?` optionality). ```typescript interface User { id: number; name: string; email: string; } // Updates accept partial properties function updateUser(id: number, fieldsToUpdate: Partial<User>) { console.log("Updating:", id, fieldsToUpdate); } updateUser(101, { email: "new@devloom.dev" }); // Valid! ``` ### 3. Pick<T, K> & Omit<T, K> - **`Pick<T, K>`**: Constructs a type by picking a subset of keys `K` from `T`. - **`Omit<T, K>`**: Constructs a type by copying all properties from `T` and then removing specified keys `K`. ```typescript // Pick only 'name' and 'email' type UserPreview = Pick<User, "name" | "email">; // Omit sensitive 'id' property type CreateUserDTO = Omit<User, "id">; const newUser: CreateUserDTO = { name: "Sarah", email: "sarah@devloom.dev", }; ``` ### 4. Readonly<T> - **`Readonly<T>`**: Marks all properties in `T` as `readonly`, preventing property assignment mutations. ```typescript const frozenUser: Readonly<User> = { id: 101, name: "Alex", email: "alex@devloom.dev", }; // frozenUser.name = "New Name"; // Error: Cannot assign to read-only property ``` ### 5. Common Mistakes - **Overusing Omit with Typos**: `Omit<T, "misspelledKey">` won't throw a compile error if the key doesn't exist on T unless validated. Use `Pick` when you want strict key validation! ### 6. Next Steps Use utility types to prevent redundant interface declarations. Next, let's explore Record, Exclude, Extract, and ReturnType!
TypeScript erases entirely at build time, so a `string` annotation produces no runtime check whatsoever. A value arriving from an API is whatever the server actually sent, regardless of what the annotation claims.
`let x = "GET"` infers `string` because the binding can change; `const x = "GET"` infers the literal `"GET"`. That widening rule is why object properties need `as const` to stay narrow.
`string[]` is any number of strings; `[string, number]` is exactly two, in that order. `readonly` removes the mutating methods at compile time, so `push` becomes a type error rather than a runtime surprise.