Skip to content

Instantly share code, notes, and snippets.

@icanhasjonas
Created October 31, 2018 04:59
Show Gist options
  • Save icanhasjonas/676697d5ee9eb52f9721176c47692db4 to your computer and use it in GitHub Desktop.
Save icanhasjonas/676697d5ee9eb52f9721176c47692db4 to your computer and use it in GitHub Desktop.
Fully Type Checked and Filtered configuration context for components
type PropertyNames<T> = keyof T
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Filtered<T, C> = { [K in keyof T]: T[K] extends C ? K : never }[keyof T]
class ConfigurationPageContext<T> {
addTextSetting<K extends PropertyNames<T>>(
field: Extract<K, Filtered<T, string>>,
title: string,
defaultValue: string = null
): ConfigurationPageContext<Omit<T, K>> {
return this
}
addCheckboxSetting<K extends PropertyNames<T>>(
field: Extract<K, Filtered<T, boolean>>,
title: string,
defaultValue: string = null
): ConfigurationPageContext<Omit<T, K>> {
return this
}
addRangeSetting<K extends PropertyNames<T>>(
field: Extract<K, Filtered<T, number>>,
title: string,
defaultValue: string = null
): ConfigurationPageContext<Omit<T, K>> {
return this
}
addQuerySetting<K extends PropertyNames<T>>(
field: Extract<K, Filtered<T, string>>,
title: string,
defaultValue: string = null
): ConfigurationPageContext<Omit<T, K>> {
return this
}
addTextAreaSetting<K extends PropertyNames<T>>(
field: Extract<K, Filtered<T, string>>,
title: string,
defaultValue: string = null
): ConfigurationPageContext<Omit<T, K>> {
return this
}
addDescription(description: string): this {
return this
}
}
class ComponentConfigurationContext<T> {
addSettingsPage(pageCallback: (pageContext: ConfigurationPageContext<T>) => void) {}
}
abstract class SomeComponentBase<Props> {
abstract configure(context: ComponentConfigurationContext<Props>)
}
const defaultGraphQlQuery = `
query {
someQuery( $a: string ) {
id
name
value
}
}
`
interface ComponentProps {
name: string
title: string
max: number
valid: boolean
query: string
}
class PatricksComponent extends SomeComponentBase<ComponentProps> {
configure(context: ComponentConfigurationContext<ComponentProps>) {
context.addSettingsPage(page =>
page
.addTextSetting('name', 'Name')
.addCheckboxSetting('valid', 'Is Valid')
.addDescription('Heads Up: The query must retuirn `id` and `name`')
.addQuerySetting('query', 'GraphQL query', defaultGraphQlQuery)
.addRangeSetting('max', 'Range')
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment