Skip to content

Instantly share code, notes, and snippets.

@rbelling
Created August 18, 2022 20:36
Show Gist options
  • Save rbelling/bf4dfe74a5e4817bc838e5058227450c to your computer and use it in GitHub Desktop.
Save rbelling/bf4dfe74a5e4817bc838e5058227450c to your computer and use it in GitHub Desktop.
Replace Props - given a type, replaces the provided props in it and returns the resulting type
import { Except, Merge } from "type-fest";
/**
* @description Merge `ReplacedProps` in `T`, excluding keys of `ReplacedProps` that are not originally in T.
* @example
* ```typescript
* type FooBar = { foo: string, bar: string }
*
* type FooBarReplaced = ReplacedProps<FooBar, { bar: number }>
*
* const hello: FooBarReplaced = { foo: "hello", bar: 42 } // Correct
* const halo: FooBarReplaced = { foo: "hello", bar: "world" } // Error! we said bar should be number
*
* // Also, if passing an unknown prop in the second argument, you won't be able to use it downstream. This is useful to catch typos.
* type FooBarWithTypo = ReplacedProps<FooBar, { baz: number }>
* const hola: FooBarWithTypo = { foo: "hello", bar: "world" } // Correct, since we mapped the unknown type `baz` leaving `bar` as string
* const ciao: FooBarWithTypo = { foo: "hello", baz: 42 } // Error, `baz` doesn't exist in FooBarWithTypo
* ```
* */
export type ReplaceProps<T, ReplacedProps extends Partial<Record<keyof T, unknown>>> = Merge<
T,
Except<ReplacedProps, keyof { [KeyType in Exclude<keyof ReplacedProps, keyof T>]?: never }>
>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment