Created
July 17, 2025 12:50
-
-
Save ortense/072972a05ef533247eaa04351dc42cf0 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
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> | |
); | |
} |
This file contains hidden or 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
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>)}</>; | |
} |
This file contains hidden or 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
// 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', | |
}, | |
}, | |
}, | |
}; | |
} |
This file contains hidden or 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
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