Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Type Systems & Props Design - Exploring PropTypes, TypeScript, Flow & Reason

Type Systems & Props Design - Exploring PropTypes, TypeScript, Flow & Reason

Badly designed props can lead to components that are frustrating to use. While there are a couple patterns to make components more pleasant to use, ultimately it needs a type system in combination with a good editor integration for an even better developer experience. Yet not all type systems are the same. They offer different features and therefore lead to different experiences.

Nikolaus Graf

November 30, 2018
Tweet

More Decks by Nikolaus Graf

Other Decks in Programming

Transcript

  1. export enum Direction { Up = "up", Down = "down"

    } interface Props { direction: Direction; } import { Direction } from "./Arrow"; <Arrow direction={Direction.Left} />
  2. interface DraftPost { status: "draft"; content: String; } interface PublishedPost

    { status: "published"; content: String; publishedAt: Date; } type Props = DraftPost | PublishedPost;
  3. export default function Post(props: Props) { switch (props.status) { case

    "draft": return <div>{props.content}</div>; case "published": return <div>{props.content}{props.publishedAt}</div>; } }
  4. interface DraftPost { status: "draft"; content: String; } interface PublishedPost

    { status: "published"; content: String; publishedAt: Date; } type Post = DraftPost | PublishedPost; interface Props { post: Post; }
  5. type DraftPost = { status: "draft", content: string }; type

    PublishedPost = { status: "published", content: string, publishedAt: Date }; type Props = DraftPost | PublishedPost;
  6. export default function Post(props: Props) { switch (props.status) { case

    "draft": return <div>{props.content}</div>; case "published": return <div>{props.content}{props.publishedAt}</div>; default: return null; } }
  7. type DraftPost = {| status: "draft", content: string |}; type

    PublishedPost = {| status: "published", content: string, publishedAt: Date |}; type Props = DraftPost | PublishedPost;
  8. let component = ReasonReact.statelessComponent("Arrow"); let make = (~post: post, _children)

    => { ...component, render: _self => switch (post) { | Draft(content) => <div> content->s </div> | Published(content, timestamp) => <div> content->s timestamp->string_of_int->s </div> }, };
  9. <Query<ProfileData> query={getProfile}> {({ data, loading, error }) => { if

    (loading) return "Loading …"; if (error) return "Loading …"; if (!data) return null; return <div>{data.user.name}</div>; }} </Query>;
  10. <Query<ProfileData> query={getProfile}> {({ result }) => { switch (result.type) {

    case "loading": return "Loading …"; case "error": return "Sorry, something went wrong"; case "data": return <div>{result.data.user.name}</div>; default: return assertNever(result); } }} </Query>;
  11. <GetUserQuery variables=userQuery##variables> ...{ ({result}) => switch (result) { | Loading

    => <div> "Loading"->s </div> | Error(error) => <div> error##message->s </div> | Data(response) => <div> response##user##name->s </div> } } </GetUserQuery>;