Skip to content

Instantly share code, notes, and snippets.

@ortense
Created July 17, 2025 12:50
Show Gist options
  • Save ortense/072972a05ef533247eaa04351dc42cf0 to your computer and use it in GitHub Desktop.
Save ortense/072972a05ef533247eaa04351dc42cf0 to your computer and use it in GitHub Desktop.
import { Setting } from '@/components/Setting'
// Example usage of the Setting component
export function ExampleUsage() {
// the value at render funcition is always correctly typed
return (
<div>
{/* Example 1: Accessing simple configuration */}
<Setting id="checkout" render={(value) => <div>Checkout: {JSON.stringify(value)}</div>} />
{/* Example 2: Nested configuration */}
<Setting
id="checkout.layout.shippingOptions.description"
render={(value) => <div>Description: {value}</div>}
/>
{/* Example 3: Conditional rendering */}
<Setting
id="checkout.layout.shippingOptions.tittle"
render={(value) => {
if (value === 'label') return <h1>Show label</h1>;
if (value === 'name') return <h1>Show name</h1>;
if (value === 'none') return <h1>Hide title</h1>;
console.warn('unknown value');
return <h1>Unknown value</h1>;
}}
/>
</div>
);
}
import * as React from 'react';
import type { ValueAtPath, Paths } from './utility';
import { useAppSettings, type AppSettings } from './useAppSettings';
function getValue<T, P extends string>(obj: T, path: P): ValueAtPath<T, P> {
return path.split('.').reduce((acc: unknown, key) => {
if (acc && typeof acc === 'object' && acc !== null && key in acc) {
return (acc as Record<string, unknown>)[key];
}
return undefined;
}, obj as unknown) as ValueAtPath<T, P>;
}
export type SettingProps<P extends Paths<AppSettings>> = {
id: P;
render: (value: ValueAtPath<AppSettings, P>) => React.ReactNode;
};
export function Setting<P extends Paths<AppSettings>>({ id, render }: SettingProps<P>) {
const settings = useAppSettings();
const value = getValue(settings, id);
if (value === undefined || value === null) {
console.warn(`[Setting] Path not found: "${id}"`);
return null;
}
return <>{render(value as ValueAtPath<AppSettings, P>)}</>;
}
// remote settings example
export type AppSettings = {
checkout: CheckoutSettings;
};
export type CheckoutSettings = {
layout: {
shippingOptions: ShippingOptionsLayoutSettings;
};
};
export type ShippingOptionsLayoutSettings = {
description: 'date' | 'none';
tittle: 'label' | 'name' | 'none';
};
export function useAppSettings(): AppSettings {
// MOCK: get the remote settings from somewhere
return {
checkout: {
layout: {
shippingOptions: {
description: 'date',
tittle: 'label',
},
},
},
};
}
export type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
export type Join<K, P> = K extends string ? (P extends string ? `${K}.${P}` : never) : never;
export type Paths<T> = {
[K in keyof T]: T[K] extends object
? T[K] extends Array<unknown>
? K // ignore arrays
: Join<K, Paths<T[K]>> | K
: K;
}[keyof T];
export type ValueAtPath<T, P extends string> = P extends `${infer K}.${infer Rest}`
? K extends keyof T
? ValueAtPath<T[K], Rest>
: never
: P extends keyof T
? T[P]
: never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment