I'm trying to create a Overwrite
type that can overwrite an existing type's properties with a different type. For instance:
type TypeA = { prop1: string; prop2: number };
type OverwrittenType = Overwrite<TypeA, { prop2: string }>;
// OverwrittenType is now equivalent to { prop1: string; prop2: string }
I found this SO answer which does the job nicely, however it's a bit too permissive for my liking, as it allows you to replace properties that were never in the original type to begin with.
type TypeA = { prop1: string; prop2: number };
type OverwrittenType = Overwrite<TypeA, { prop3: string }>;
// OverwrittenType is now equivalent to { prop1: string; prop2: number; prop3: string }
Below is the Overwrite
type from that other thread.
type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
How do I need to modify it to prohibit replacement keys that are not present in the initial type?
type TypeA = { prop1: string; prop2: number };
type OverwrittenType = Overwrite<TypeA, { prop3: string }>; // Throw some sort of error here, prop3 is not a key of TypeA
CodePudding user response:
You can add a condition on you generic !
type Overwrite<T extends { [key in keyof U]: any }, U> = Omit<T, keyof U> & U;
type TypeA = { prop1: string; prop2: number };
type OverwrittenType = Overwrite<TypeA, { prop1: number }>; // ok
const foo: OverwrittenType = { prop1: 3, prop2: 3 }
type OverwrittenType2 = Overwrite<TypeA, { prop3: number }>; // error
const bar: OverwrittenType = { prop1: 3, prop3: 3 }
CodePudding user response:
You could achieve this with a mapped type like this:
type TypeA = { prop1: string; prop2: number };
type Overwrite<T, U extends Partial<Record<keyof T, any>>> = { [Key in keyof T]: undefined extends U[Key] ? T[Key] : U[Key] };
type OverwrittenTypeWorks = Overwrite<TypeA, { prop2: string }>; // { prop1: string, prop2: string }
type WrongOverwrittenType = Overwrite<TypeA, { prop3: string }>; // Throw some sort of error here, prop3 is not a key of TypeA