Пытаюсь сделать функцию, которая бы создавала конфиг для сайта. То есть первым аргументом идет общий конфиг для всех env'ов, а дальше объект, в котором ключи - это названия env'ов, а значения - конфиги, специфичные для каждого env'а.
То есть логика такая: первым аргументом может быть объект с любыми ключами и значениями. А вот последующие конфиги могут либо перезаписывать дефолтные ключи (таким же типом данных) либо добавлять новые ключи. Но при этом, если в каком-то из конфигов есть ключ, которого нет в дефолтном конфиге, он обязательно должен быть прописан во всех конфигах.
Надеюсь с примером будет понятно. У меня что-то получилось, но работает не до конца верно (такой вариант пропускает пустые конфиги). Да и вангую что есть более лаконичное решение, мое попахивает говнокодом. Не понимаю почему мне так сложно TS дается, понимаю как все работает по отдельности, но когда нужно какой-то сложный generic написать, начинаю жутко тупить.
export const createConfig = <
Default extends Record<string, any>,
Configs extends Record<string, Record<string, any>>,
X = Configs extends Record<string, infer X> ? Omit<X, keyof Default> : never
>(
common: Default,
configs: {
[env in keyof Configs]: {
[key in keyof Configs[env]]: key extends keyof Default ? Default[key] : (
key extends keyof X ? (
X[key] extends Configs[env][key] ? Configs[env][key] : never
) : never
)
}
}
) => {}
Должно ругаться на пустой конфиг для staging:
const config = createConfig(
{
test: 12345,
hello: true
},
{
staging: {
// hostname: ""
},
production: {
hostname: "hello"
}
},
)