You could invert it to compose instead of extend, so something like this: ```elm -- Button with a Label MyButton.view [ MyButton.label "blah" ]
-- Button with an Icon MyButton.view [ MyButton.icon "iconId" ] -- Button with both MyButton.view [ MyButton.label "blah", MyButton.icon "iconId" ] ``` You can easily enforce the icon to always render before the label is that is a requirement, regardless of position in the list, etc... etc... This is how the `elm-mdl` package works for example. On Friday, August 19, 2016 at 11:46:30 AM UTC-6, suttlecommakevin wrote: > > Apologies if this has been posted elsewhere, but I keep coming back to it. > > Let's get basic. Like *super *basic. > > I get a spec from a designer for a button with 3 types of children. > > 1. A button with a label only > 2. A button with an icon only > 3. A button with an icon *and* a label > > > In a object-oriented programming environment, you could make a ButtonBase > class and extend it. > In React's bizarro world, they try to promote this Higher-order Components > technique, which is really just a function factory. > In Flow, you can at least start making types, and then, share and > intersect <https://flowtype.org/docs/functions.html#overloading> them. > > > *ButtonProps.js* > > // @flow > /* eslint-disable import/prefer-default-export */ > > export type ButtonProps = { > type?: 'button' | 'reset' | 'submit', > design: 'primary' | 'secondary', > className?: string, > children?: Array<HTMLElement>, > onClick?: () => void, > onFocus?: () => void, > onmouseover?: () => void, > onmouseout?: () => void, > } > > > *Button.jsx* > > // @flow > > import React from 'react'; > import type { ButtonProps } from './ButtonProps'; > import './Button.css'; > > /* eslint-disable flowtype/space-after-type-colon */ > const Button = ({ > design = 'primary', > className = 'btn', > type = 'button', > children } :ButtonProps) => > > <button className={[`${design} ${className}`]} type={type}> > {children} > </button>; > > export default Button; > > > *Icon.jsx* > > // @flow > > import React from 'react'; > import Button from './Button.jsx'; > import type { ButtonProps } from './ButtonProps'; > import Icon from '../Icons/Icon.jsx'; > import type { IconProps } from '../Icons/IconProps'; > > type IconButtonProps = ButtonProps & IconProps; > > const IconButton = (props: IconButtonProps) => > <Button > design={props.design} > onClick={props.onClick} > className={`iconBtn ${props.className}`} > > > <Icon glyph={props.glyph} /> > </Button>; > > export default IconButton; > > > Notice this line: type IconButtonProps = ButtonProps & IconProps; which > is just a fancy Object.assign() really. > It's easy to read, easy to understand, but many would claim it doesn't > follow "best practices". > > > My question is, how would Elm/FP handle this? > > > > Thanks, folks. > -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
