Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

document @types/react #69

Merged
merged 5 commits into from
Jan 30, 2019
Merged

document @types/react #69

merged 5 commits into from
Jan 30, 2019

Conversation

swyxio
Copy link
Collaborator

@swyxio swyxio commented Jan 16, 2019

part of a larger push to flesh out the Advanced section with useful commentary and best practices on all the provided types

as started here 7b1f1f2 with @ferdaber

i definitely dont have enough experience to write this on my own, we can split this up and/or add commentary here

ADVANCED.md Outdated
- `SFC`
- `ComponentState`
- `LegacyRef`
- `ReactType`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a source for this? Looking the .d.ts source it seems like they explicitly annotate deprecated types and this is not the case for ReactType.

ReactType is pretty useful to cover most types that can be passed to createElement e.g.

function PassThrough(props: { as: ReactType<any> }) {
   const { as: Component } = props;

   return <Component />
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope it was just a quick first cut based on my experience. thats why i open up this as a PR so we can discuss :)

@ferdaber
Copy link
Collaborator

My take on the types:

Under the React namespace

  • ReactType - used for higher order components or operations on components
  • ComponentType - used for higher order components where you don't specifically deal with the intrinsic components
  • Ref - used to type innerRef
  • ReactElement - equivalent to JSX.Element
  • ReactPortal - used if you specifically need to type a prop as a portal, otherwise it is part of ReactNode
  • ReactNode - anything that is renderable inside of JSX, this is NOT the same as what can be returned from a component!
  • Component - base class of all class-based components
  • PureComponent - base class for all class-based optimized components
  • ComponentClass - a complete interface for the produced constructor function of a class declaration that extends Component, often used to type external components instead of typing your own
  • FC, FunctionComponent - a complete interface for function components, often used to type external components instead of typing your own
  • JSXElementConstructor - anything that TypeScript considers to be a valid thing that can go into the opening tag of a JSX expression
  • ComponentProps - props of a component
  • ComponentPropsWithRef - props of a component where if it is a class-based component it will replace the ref prop with its own instance type
  • ComponentPropsWithoutRef - props of a component without its ref prop
  • CSSProperties - used to type the css prop
  • all events: used to type event handlers
  • all event handlers: used to type event handlers
  • all consts: Children, Fragment, ... are all public and reflect the React runtime namespace
  • all methods: createElement, cloneElement, ... are all public and reflect the React runtime API

Under the JSX namespace

  • Element - the type of any JSX expression
  • LibraryManagedAttributes - used to resolve static defaultProps and propTypes with the internal props type of a component
  • IntrinsicElements - every possible built-in component that can be typed in as a lowercase tag name in JSX

Deprecated

  • LegacyRef
  • SFCElement
  • SFC
  • StatelessComponent

Private

Anything not listed here are considered internal types and not public.

A special note that I discourage the use of most ...Element types because of how black-boxy JSX.Element is. You should almost always assume that anything produced by React.createElement is the base type React.ReactElement.

@swyxio
Copy link
Collaborator Author

swyxio commented Jan 16, 2019

you are a stud. will update accordingly

Copy link
Member

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome stuff. Helps a lot to have a general resource we can point to,

ADVANCED.md Outdated Show resolved Hide resolved
ADVANCED.md Outdated

Most Commonly Used Interfaces and Types

- `ReactNode` - anything that is renderable *inside* of JSX, this is NOT the same as what can be returned from a component!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this used to be JSXElement. master currently says otherwise:

but React.ReactNode is the set of all possible return values of a component.

Maybe switch from returned from to rendered by? It's IMO slightly ambiguous in its current form.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes i edited it. ok.

ADVANCED.md Outdated
- all methods: `createElement`, `cloneElement`, ... are all public and reflect the React runtime API


A special note that I discourage the use of most `...Element` types because of how black-boxy `JSX.Element` is. You should almost always assume that anything produced by `React.createElement` is the base type `React.ReactElement`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like this should be under "Namespace: JSX". Also explicitly state who said that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i struggled with where to put this too, but put it in the React namespace because he's actually talking about createElement and cloneElement etc

ADVANCED.md Outdated

**Don't use/Internal/Deprecated**

Anything not listed above are considered internal types and not public.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Anything not listed above are considered internal types and not public.
Anything not listed above is considered an internal type and not public. If you're not sure you can check out the source of `@types/react`. The types are annotated accordingly.

Typo suggestion from https://www.dummies.com/education/language-arts/grammar/tricky-grammar-is-it-singular-or-plural/

While it seems like this is true for @deprecated it doesn't seem like @internal is used. This is an experimental feature though. Is there some way to verify what types are internal?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to @ferdaber its not documented what is internal vs not...

@swyxio
Copy link
Collaborator Author

swyxio commented Jan 30, 2019

merging for now.

@swyxio swyxio merged commit a482ca3 into master Jan 30, 2019
@swyxio swyxio deleted the document-types-react branch January 30, 2019 04:49
@havenchyk
Copy link

@sw-yx @ferdaber @eps1lon

This example is clear, but what if we want also to extend type definitions of our component with type definitions from passed via as= component?

E.g. <MUILink as={RouterLink} to='/'>Home</MUILink>. Obviously, to is not defined on MUILink, but defined on type of RouterLink.

I'm sorry if it's not a proper place to ask this question, I also added more detailed question at SO, but just in case you already stumbled upon with solution, it would be nice to know it ;)

Also I think it will be a nice addition to current examples here.

Thanks for all your work here, really nice information!

@eps1lon
Copy link
Member

eps1lon commented Sep 2, 2019

@havenchyk This should work (with some caveats) with material-ui typings.

Explaining what and how this works and what doesn't or needs extra attention needs quite a lot of explaining though. I do want to write a comprehensive summary of polymorphic react components. I'm not sure if this cheatsheet is appropriate though (since this is a very complicated issue) or if this will be part of the material-ui docs or some blog post.

If you're just starting out I would highly recommend not using something like <Link as={RouterLink} /> or <Link component={RouterLink} /> but rather use a render prop which is explained in https://blog.andrewbran.ch/polymorphic-react-components/.

The as prop is currently impossible to type correctly while also being able to define a prop interface for consumption.

@havenchyk
Copy link

havenchyk commented Sep 2, 2019

@eps1lon I saw the solution in Material UI, as I got it, as is omitted and then added later, it works but has caveats e.g. unreadable compiler error (instead of to is missing, it's something generic).

But anyhow, thanks @eps1lon at least I have a direction for investigation.

As for discussion of the pros and cons of the approaches, what the place would you recommend? Can I create a new issue in this repo? /cc @sw-yx

@swyxio
Copy link
Collaborator Author

swyxio commented Sep 2, 2019

of course

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants