$30 off During Our Annual Pro Sale. View Details »

TypeScript Patterns for Better React Components

TypeScript Patterns for Better React Components

Have you ever tried building fully-typed polymorphic components? Good! Now how about combining that with discriminated unions, enhanced HTML attribute types and a forwardRef wrapper? Exactly — it's not easy. In this talk, we'll walk you through several TypeScript patterns you'll face over and over again. From building simple but 100% type-safe component props, constructing compound vs. polymorphic components, to function overload components, discriminated union props, generic React components and augmented components wrapped in forwardRef and more. Join this session and bring your typing skills to the next level!

Glenn Reyes

October 06, 2023
Tweet

More Decks by Glenn Reyes

Other Decks in Programming

Transcript

  1. @glnnrys · glennreyes.com
    TypeScript Patterns
    for Better React Components

    View Slide

  2. Glenn Reyes
    @glnnrys · glennreyes.com
    Software Engineer, Tech Speaker &
    Workshop Instructor


    Head of Developer Relations
    @
    Kadena

    View Slide

  3. Marmelade


    NFT standard at Kadena
    Kadena


    The only PoW blockchain that scales
    Chainweb


    A scalable PoW consensus
    algorithm
    Remote first & distributed
    Founded by


    Stuart Popejoy &


    Will Martino
    kadena.js


    github.com/kadena-community/kadena.js
    ~
    30 developers in DX team
    ~
    70 employees
    Pact


    The human-readable smart contract language

    View Slide

  4. @glnnrys
    React

    View Slide

  5. @glnnrys
    Typing in React

    View Slide

  6. @glnnrys
    History of typing in React

    View Slide

  7. @glnnrys
    History of typing in React

    View Slide

  8. @glnnrys
    History of typing in React

    View Slide

  9. @glnnrys
    History of typing in React

    View Slide

  10. @glnnrys
    History of typing in React

    View Slide

  11. @glnnrys
    History of typing in React

    View Slide

  12. @glnnrys
    History of typing in React

    View Slide

  13. @glnnrys
    History of typing in React

    View Slide

  14. @glnnrys
    History of typing in React

    View Slide

  15. @glnnrys
    History of typing in React

    View Slide

  16. @glnnrys
    History of typing in React
    🤖

    View Slide

  17. @glnnrys
    From the beginning …

    View Slide

  18. @glnnrys
    TypeScript has been tightly
    integrated with Angular and Vue

    View Slide

  19. @glnnrys
    But not with React 🫠

    View Slide

  20. @glnnrys
    Today, TypeScript is not


    tightly integrated with React.

    View Slide

  21. @glnnrys

    View Slide

  22. @glnnrys
    DefinitelyTyped on GitHub
    TypeScript types for React are
    purely driven by the community.

    View Slide

  23. @glnnrys
    @types/react


    @types/react-dom

    View Slide

  24. @glnnrys
    Patterns

    View Slide

  25. @glnnrys
    Boolean props

    View Slide

  26. @glnnrys
    Boolean props

    View Slide

  27. @glnnrys
    Boolean props

    View Slide

  28. @glnnrys
    Boolean props

    View Slide

  29. @glnnrys
    Boolean props

    View Slide

  30. @glnnrys
    String literal union type prop

    View Slide

  31. @glnnrys
    String literal union type prop

    View Slide

  32. @glnnrys
    String literal unions vs. enums

    View Slide

  33. @glnnrys
    String literal unions vs. enums
    Differences
    ‣ Distinct types

    View Slide

  34. @glnnrys
    String literal unions vs. enums

    View Slide

  35. @glnnrys
    String literal unions vs. enums
    Differences
    ‣ Runtime overhead with enum

    View Slide

  36. @glnnrys
    String literal unions vs. enums
    Differences
    ‣ Runtime overhead with string literal unions

    View Slide

  37. @glnnrys
    Comparison
    boolean vs. union







    View Slide

  38. @glnnrys
    Comparison
    boolean vs. union vs. custom











    View Slide

  39. @glnnrys
    Custom component
    In comparison to boolean vs. union

    Predefined logic built-in to the component


    ‣ Button is tightly integrated with form context


    ‣ loading and disabled state coming from a form library


    Appearance identical to the primitive

    View Slide

  40. @glnnrys
    Components with HTML
    element attribute

    View Slide

  41. @glnnrys

    View Slide

  42. @glnnrys

    View Slide

  43. @glnnrys
    Components with HTML element attributes
    ‣ React.HTMLAttributes does not include enough types

    View Slide

  44. @glnnrys
    Components with HTML element attributes
    ‣ React.HTMLProps uses AllHTMLAttributes → inaccurate types

    View Slide

  45. @glnnrys
    Components with HTML element attributes
    ‣ JSX.IntrinsicElements errors when inlined

    View Slide

  46. @glnnrys
    Components with HTML element attributes
    • Workaround: JSX.IntrinsicElements wrapped in NonNullable

    View Slide

  47. @glnnrys
    Components with HTML element attributes
    React.ButtonHTMLAttributes

    View Slide

  48. @glnnrys
    Components with HTML element attributes

    View Slide

  49. @glnnrys
    Components with HTML element attributes

    View Slide

  50. @glnnrys
    React.FunctionComponent

    View Slide

  51. @glnnrys
    React.FunctionComponent

    View Slide

  52. @glnnrys
    React.FunctionComponent
    Definition (since React 18
    )
    Usage

    View Slide

  53. @glnnrys
    React Server Components

    View Slide

  54. @glnnrys
    React Server Components

    View Slide

  55. @glnnrys
    React Server Components
    Async React components are
    supported since TypeScript 5.1 🚀

    View Slide

  56. @glnnrys
    Reusing types and interfaces

    View Slide

  57. @glnnrys
    Reusing types and interfaces

    View Slide

  58. @glnnrys
    Reusing types and interfaces
    vs.

    View Slide

  59. @glnnrys
    Prefer reusability and keep
    simplicity on a case-by-case basis.

    View Slide

  60. @glnnrys
    Compound and Polymorphic Components
    A comparison
    vs.

    View Slide

  61. @glnnrys
    Compound and Polymorphic Components
    A comparison
    vs.
    Customization to the icon is managed by the
    DownloadIcon component itself

    Flexibility
    Customization to the icon is managed
    by the Icon primitive

    Consistency

    View Slide

  62. @glnnrys
    Compound Components
    asChild from radix

    View Slide

  63. @glnnrys
    Compound Components
    asChild from radix

    View Slide

  64. @glnnrys
    Compound Components
    asChild from radix

    View Slide

  65. @glnnrys
    Compound Components
    asChild from radix

    View Slide

  66. @glnnrys
    Polymorphic Components




    View Slide

  67. @glnnrys
    Polymorphic Components

    View Slide

  68. @glnnrys
    Polymorphic Components

    View Slide

  69. @glnnrys
    Generic Components

    View Slide

  70. @glnnrys
    Generic Components

    View Slide

  71. @glnnrys
    Generic Components

    View Slide

  72. @glnnrys
    React.forwardRef

    View Slide

  73. @glnnrys
    React.forwardRef

    View Slide

  74. @glnnrys
    React.forwardRef
    ?

    View Slide

  75. @glnnrys
    React.forwardRef

    View Slide

  76. @glnnrys
    React.forwardRef

    View Slide

  77. @glnnrys
    React.forwardRef

    View Slide

  78. @glnnrys
    React.forwardRef

    View Slide

  79. @glnnrys
    React.Context

    View Slide

  80. @glnnrys
    React.Context
    With default values

    View Slide

  81. @glnnrys
    React.Context
    With default values

    View Slide

  82. @glnnrys
    React.Context
    With default values

    View Slide

  83. @glnnrys
    React.Context
    With default values

    View Slide

  84. @glnnrys
    React.Context
    Without default values

    View Slide

  85. @glnnrys
    React.Context
    Without default values

    View Slide

  86. @glnnrys
    React.Context
    Without default values

    View Slide

  87. @glnnrys
    Overload function components

    View Slide

  88. @glnnrys
    Overload function components

    View Slide

  89. @glnnrys
    type vs. interface

    View Slide

  90. @glnnrys
    type vs. interface
    type
    interface

    View Slide

  91. @glnnrys
    Reduced computational work


    By using interface.

    View Slide

  92. @glnnrys
    Prefer interface


    for faster TS compilation


    in your editor.

    View Slide

  93. @glnnrys
    Encourage type annotations.
    Especially function return types, for faster compilation

    View Slide

  94. @glnnrys

    View Slide

  95. @glnnrys
    Commenting types


    is very encouraged.

    View Slide

  96. @glnnrys
    Commenting types
    dayjs Example

    View Slide

  97. @glnnrys
    Commenting types
    dayjs Example

    View Slide

  98. @glnnrys
    any

    View Slide

  99. @glnnrys
    It’s your friend, but it’s also not.
    any

    View Slide

  100. @glnnrys
    Run time parsing

    View Slide

  101. @glnnrys
    any, as and !

    View Slide

  102. @glnnrys
    Avoid them all.
    any, as and !

    View Slide

  103. @glnnrys
    any, as and !
    Type narrowing with type guards

    View Slide

  104. @glnnrys
    any, as and !
    Type narrowing with type guards

    View Slide

  105. @glnnrys
    any, as and !
    Runtime parsing

    View Slide

  106. @glnnrys
    Tooling

    View Slide

  107. @glnnrys
    Great tooling


    keeps your codebase clean


    without the hassle.

    View Slide

  108. type-fest
    Tooling
    ts-pattern
    esbuild
    tsx


    (formerly esno)
    ts-reset


    Improved built-in typings
    bun
    typescript-eslint


    eslint-config-banana

    View Slide

  109. @glnnrys
    Configuration

    View Slide

  110. @glnnrys

    View Slide

  111. @glnnrys

    View Slide

  112. @glnnrys

    View Slide

  113. @glnnrys
    One last thing


    before we wrap up …

    View Slide

  114. @glnnrys
    Glenn Reyes, @glnnrys
    “Using TypeScript is most fun when the
    amount of possibilities of errors and
    edge cases are zero or close to zero.”

    View Slide

  115. Thank You!
    @glnnrys · glennreyes.com

    View Slide