leveraging-partial-types-readonly-and-pick
Leveraging Partial Types, Readonly, and Pick:
Use of Partial Types:
interface User {
id: number;
name: string;
email: string;
}
function updateUser(id: number, updates: Partial<User>) {
// Function to update a user with only the fields provided in updates.
}Creating Update Patterns with Partial:
function applyPatch<T>(object: T, patch: Partial<T>): T {
return { ...object, ...patch };
}
// Usage:
const originalUser = { id: 1, name: 'John', email: 'john@example.com' };
const updatedUser = applyPatch(originalUser, { email: 'john.doe@example.com' });Readonly for Immutability:
interface ImmutableUser {
readonly id: number;
readonly name: string;
readonly email: string;
}
const user: ImmutableUser = { id: 1, name: 'Jane', email: 'jane@example.com' };
// user.name = 'John'; // Error: Cannot assign to 'name' because it is a read-only property.Protecting State with Readonly:
function freezeUser(user: Readonly<User>) {
// Now user's properties cannot be altered.
}
// Usage:
freezeUser({ id: 2, name: 'Doe', email: 'doe@example.com' });Mapping Types to Readonly:
type ReadonlyUser = Readonly<User>;
// Usage:
let readOnlyUser: ReadonlyUser = { id: 3, name: 'Smith', email: 'smith@example.com' };
// readOnlyUser.id = 4; // Error: Cannot assign to 'id' because it is a read-only property.Pick for Selecting Properties:
type UserEmail = Pick<User, 'email'>;
// Usage:
const userEmail: UserEmail = { email: 'selective@example.com' };
// userEmail.id; // Error: Property 'id' does not exist on type 'UserEmail'.Creating Subtypes with Pick:
type UserInfo = Pick<User, 'id' | 'name'>;
function displayUserInfo(userInfo: UserInfo) {
// Function to display user information without exposing the email.
}
// Usage:
displayUserInfo({ id: 4, name: 'Alex' });- Combining Partial with Readonly:
type PartialReadonlyUser = Partial<Readonly<User>>;
// Usage:
const newUser: PartialReadonlyUser = { name: 'New Name' }; // Only 'name' is set, rest are optional.
// newUser.name = 'Another Name'; // Error: Cannot assign to 'name' because it is a read-only property.TypeScript's Structural Typing with Partial and Pick:
// Assume User type from previous example.
type PartialName = Partial<Pick<User, 'name'>>;
// Usage:
const userWithPartialName: PartialName = { name: 'Optional Name' }; // 'name' is optional, other User properties are not present.Utility Types in APIs:
function updateUserData(userId: number, updates: Partial<User>): Readonly<User> {
// Function that updates user and returns a Readonly version of User.
// Implementation here...
return {} as Readonly<User>;
}Refactoring with Readonly and Pick:
type ReadonlyUserInfo = Readonly<Pick<User, 'id' | 'name'>>;
function getUserInfo(userId: number): ReadonlyUserInfo {
// Refactored function that returns only the id and name, both as readonly.
// Implementation here...
return {} as ReadonlyUserInfo;
}Nested Partial Types:
interface NestedUser {
id: number;
profile: {
name: string;
address: {
street: string;
city: string;
};
};
}
type PartialNestedUser = Partial<{
[P in keyof NestedUser]: Partial<NestedUser[P]>
}>;
// Usage:
const partialNestedUser: PartialNestedUser = { profile: { address: { city: 'City Name' } } };Leveraging Utility Types for Function Signatures:
function processUser(user: Readonly<Pick<User, 'id' | 'name'>>): Partial<User> {
// Process the user and possibly return partial updates.
// Implementation here...
return { email: 'newemail@example.com' };
}Extendability with Utility Types:
type CustomUserType = Readonly<Partial<Pick<User, 'name' | 'email'>>>;
// Usage:
const customUser: CustomUserType = { name: 'Custom Name' }; // 'email' is optional, 'id' is not included.Advanced Mapped Types with Readonly and Pick:
type AdvancedMappedType<T> = {
[P in keyof T as P extends 'sensitive' ? never : P]: Readonly<Pick<T, P>>
};
interface UserWithSensitiveData {
id: number;
name: string;
sensitive: {
ssn: string;
password: string;
};
}
type SafeUser = AdvancedMappedType<UserWithSensitiveData>;
// Usage:
const safeUser: SafeUser = {
id: 1,
name: 'John Doe',
// 'sensitive' property is omitted due to conditional mapped type.
};