Skip to content

Instantly share code, notes, and snippets.

@luggage66
Last active March 7, 2019 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luggage66/feb1dc4dddc8f38bf01f051378a055b6 to your computer and use it in GitHub Desktop.
Save luggage66/feb1dc4dddc8f38bf01f051378a055b6 to your computer and use it in GitHub Desktop.
TS to change a type based on a "config type"
// original code by MadaraUchiha
// Just defines named types we can reference by key. Never used as a real value type.
interface Operations<T> {
'delete': never;
'nullable': T | null;
'box': {value: T};
};
type MemberConfig<T> = keyof Operations<T>;
type ObjectConfig<T> = {
[K in keyof T]?: MemberConfig<T[K]>
};
type OmitNevers<T> = Pick<T, {[K in keyof T]: T[K] extends never ? never : K}[keyof T]>;
type ApplyConfig<T, C extends ObjectConfig<T>> = OmitNevers<{
[K in keyof T]: C[K] extends MemberConfig<T[K]> ? Operations<T[K]>[C[K]] : T[K]
}>;
interface OriginalType {
foo: string;
bar: boolean;
baz: number;
bux: Date;
}
// The money shot
type NewType = ApplyConfig<OriginalType, {
foo: 'delete';
bar: 'box';
baz: 'nullable';
// don't specify bux, it should pass through unchanged.
}>;
declare const x: NewType;
const a = x.foo; // error, we deleted foo
const b = x.bar.value;
const c = x.baz.toFixed(2); // error, might be calling .toFixed() on null
const d = x.bux;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment