Skip to content

Instantly share code, notes, and snippets.

@Soul-Master
Last active June 19, 2018 06:12
Show Gist options
  • Save Soul-Master/bbc0cff8d5d7fbbf4aea93eab71ef66b to your computer and use it in GitHub Desktop.
Save Soul-Master/bbc0cff8d5d7fbbf4aea93eab71ef66b to your computer and use it in GitHub Desktop.
type JSONified<T> =
JSONifiedValue<T extends { toJSON(): infer U } ? U : T>;
type JSONifiedValue<T> =
T extends string | number | boolean | null ? T :
T extends Function ? undefined :
T extends Array<infer U> ? JSONifiedArray<U> :
T extends object ? JSONifiedObject<T> :
undefined;
type UndefinedAsNull<T> = T extends undefined ? null : T;
interface JSONifiedArray<T> extends Array<UndefinedAsNull<JSONified<T>>> { }
type JSONifiedObject<T> = {
[P in keyof T]: JSONified<T[P]>
};
declare class Widget {
toJSON(): { kind: 'Widget', date: Date };
}
type Item = {
text: string;
count: number;
choice: 'yes' | 'no' | null;
func: () => void;
nested: {
isSaved: boolean;
data: [1, undefined, 2];
};
widget?: Widget;
children: Item[];
};
declare let item: JSONified<Item>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment