Skip to content

Instantly share code, notes, and snippets.

@geelen

geelen/traits.ts

Created Apr 7, 2020
Embed
What would you like to do?
ARGH TYPESCRIPT WHY WONT YOU OBEY ME
import { css } from 'styled-components'
type RulesDefn = {
[k: string]: string
}
type TrainBuilder<T extends RulesDefn> = {
[k in keyof T]: TrainBuilder<T>
} & {
toString: () => string[]
}
export const px = (num: string | number) =>
typeof num === 'string' ? num : `${num}rem`
const typography = {
small: `font-size: 1rem;`,
large: `font-size: 2rem;`,
size: (x: string | number) => `font-size: ${px(x)}`,
}
const flex: RulesDefn = {
default: `display: flex;`,
inline: `display: inline-flex;`,
vertical: `flex-direction: column;`,
align_center: `align-items: center;`,
align_start: `align-items: flex-start;`,
align_end: `align-items: flex-end;`,
align_baseline: `align-items: baseline;`,
align_stretch: `align-items: stretch;`,
center: `justify-content: center;`,
center_both: `justify-content: center; align-items: center;`,
justify_start: `justify-content: flex-start;`,
justify_end: `justify-content: flex-end;`,
justify_space_btw: `justify-content: space-between;`,
justify_space_around: `justify-content: space-around;`,
wrap: `flex-wrap: wrap;`,
fg0: `flex-grow: 0;`,
fg1: `flex-grow: 1;`,
fg2: `flex-grow: 2;`,
}
const x =css`
${typography.small().size(1.2).size('13px')};
${sizing.height(4).pt(1)};
`
function chain<T extends RulesDefn>(rules: T): TrainBuilder<T> {
class ChainLink {
private readonly rules: string[]
constructor(rules: string[]) {
this.rules = rules
}
toString() {
return this.rules
}
}
Object.keys(rules).forEach((option) => {
Object.defineProperty(ChainLink.prototype, option, {
get() {
return new ChainLink(this.rules.concat(rules[option]))
},
})
})
return (new ChainLink([rules.default]) as unknown) as TrainBuilder<T>
// return 'foo'
}
const Flex = chain(flex) as TrainBuilder<typeof typography>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment