Created
January 15, 2021 14:34
-
-
Save Interpause/e1ca9d9a1a083cbf76e49a57b9d5b463 to your computer and use it in GitHub Desktop.
The most ridiculous piece of Typescript I ever wrote just to merge nested objects and invert them while being type-strict.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file Suffering with typescript and breaking the tslinter a few times. | |
* @author John-Henry Lim <hyphen@interpause.dev> | |
*/ | |
/** K2 are the keys for the inner config. */ | |
export type InnerConfig<K2 extends keyof any,V extends keyof any> = Partial<Record<K2,V>>|V; | |
/** K1 are the keys for the outer config, K2 are the keys for the inner config. */ | |
export type LayeredConfig<K1 extends keyof any,K2 extends keyof any,V extends keyof any> = Partial<Record<K1,InnerConfig<K2,V>>>; | |
/** K1 and K2 are reversed on purpose. This is to invert the config structure. */ | |
export type DefaultLayeredConfig<K1 extends keyof any,K2 extends keyof any,V> = Readonly<Record<K2,Record<K1,V>>>; | |
/** Merges DefaultLayeredConfig with LayeredConfig, inverting the inner and outer keys in the process while also expanding any general options. See Toggle.tsx for example. */ | |
export function mergeConfigs<K1 extends keyof any,K2 extends keyof any,V extends keyof any>(defaultConfig:DefaultLayeredConfig<K1,K2,V>,customConfig?:LayeredConfig<K1,K2,V>){ | |
let mergedConfig:Record<K2,Record<K1,V>> = JSON.parse(JSON.stringify(defaultConfig)); | |
(Object.entries(customConfig??{}) as [K1,InnerConfig<K2,V>][]).forEach(([k1,v1]) => (Object.entries(mergedConfig) as [K2,Record<K1,V>][]).forEach(([k2,d]) => d[k1] = typeof v1 === "object"? v1[k2]??d[k1] : v1)); | |
return mergedConfig; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment