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

[docs] Remove <any> from nextjs-with-typescript example #16555

Merged
merged 13 commits into from
Jul 17, 2019
Merged

[docs] Remove <any> from nextjs-with-typescript example #16555

merged 13 commits into from
Jul 17, 2019

Conversation

virzak
Copy link
Contributor

@virzak virzak commented Jul 10, 2019

The Use of any cause tslint warnings.
Also adding the use of FunctionComponent.

I wonder if tslint should be added to this example or if at least its rules should be followed for those who would like to add it later on.

@mui-pr-bot
Copy link

mui-pr-bot commented Jul 10, 2019

No bundle size changes comparing c54e545...f2bbcc1

Generated by 🚫 dangerJS against f2bbcc1

@oliviertassinari oliviertassinari added docs Improvements or additions to the documentation typescript labels Jul 11, 2019
@oliviertassinari
Copy link
Member

@Janpot By any chance, it would be awesome if you had the time to have a look at the changes. Thank you!

// A styled version of the Next.js Link component:
// https://nextjs.org/docs/#with-link
function RouterLink(props: LinkProps) {
const RouterLink: FunctionComponent<LinkProps> = props => {
Copy link
Member

Choose a reason for hiding this comment

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

We never use FunctionComponent in our definitions (NProgressBar exception we should probably change). Is there a reason for changing it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is due to tslint rule which prefers arrow functions to normal functions. The type of props is inferred from the function type.

Wasn't aware of typescript conventions for this project. Is it documented somewhere?

Copy link
Member

Choose a reason for hiding this comment

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

Does this rule come by default?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like they turn it on for the strictest setting, but the recommended allows named functions too. https://palantir.github.io/tslint/usage/configuration/

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

it should support the strictest tslint rules

I tend to disagree with that. IMO It should compile with strict and be a solid starting point for a mui/ts project. I think if they want to use an opinionated coding style like tslint it should up to the user to adapt the example to their needs.

Copy link
Member

Choose a reason for hiding this comment

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

I think if they want to use an opinionated coding style like tslint it should up to the user to adapt the example to their needs.

Agreed. Lint rules for programming errors or bugs: sure. Stylistic lint rules: no. Following the same convention that create-react-app applies.

This doesn't apply to the only-arrow-functions rule since the rationale doesn't apply to function components:

Traditional functions don’t bind lexical scope, which can lead to unexpected behavior when accessing ‘this’.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So what's the rationale for avoiding FunctionComponent<T>? Is this for consistency with the rest of the code? To me FunctionComponent is a clear indication that this isn't just some function, but a react component. As this guide points out, you can have access to the children prop.

It is also being used in one of the best known TypeScript books

Not an issue reverting back to previous syntax, but just curious, since I thought that was the standard.

Copy link
Member

@Janpot Janpot Jul 12, 2019

Choose a reason for hiding this comment

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

I see

import React, { FunctionComponent, PropsWithChildren } from 'react';

interface Props {
  prop: 'hello';
}

// either:
function Component1 (props: PropsWithChildren<Props>) {
  return <div>{props.children}</div>;
}

// or:
const Component2: FunctionComponent<Props> = props => <div>{props.children}</div>;

// or to have displayName
const Component3: FunctionComponent<Props> = function Component3(props) {
  return <div>{props.children}</div>;
};

makes sense to me, but I have no preference.

Copy link
Member

@eps1lon eps1lon Jul 12, 2019

Choose a reason for hiding this comment

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

As this guide points out, you can have access to the children prop.

Implicit children should be avoided since they are neither accurate nor likely to stay in the future.

So what's the rationale for avoiding FunctionComponent?

I outlined this above in #16555 (comment). TL;DR: component display names

To me FunctionComponent is a clear indication that this isn't just some function, but a react component.

99% of the time a uppercase first function is a react component in a react codebase. Uppercase first functions I only ever see in codebases that don't use class syntax.

@oliviertassinari oliviertassinari changed the title removing React.Ref<any> from nextjs-with-typescript example [example] Remove React.Ref<any> from nextjs-with-typescript example Jul 11, 2019
@Janpot
Copy link
Member

Janpot commented Jul 12, 2019

[email protected] now exposes LinkProps vercel/next.js#7905

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.

Would like to accept this with only the ref typing but the stylistic changes are motivated by a lint rule of which the rationale doesn't apply here.

props: NextComposedProps,
ref: React.Ref<any>,
) {
const NextComposed = React.forwardRef<HTMLAnchorElement, NextLinkProps>((props, ref) => {
Copy link
Member

Choose a reason for hiding this comment

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

This changes the display name in react devtools:

3.6:

- ForwardRef(NextComposed)
+ ForwardRef

experimental:

- <NextComposed> ForwardRef
+ <Anonymous> ForwardRef

Both of which are less ideal.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can have is this way:

const NextComposed = React.forwardRef<HTMLAnchorElement, NextLinkExtendedProps>(
  function NextComposed(props, ref) {

That way dev tools will show ForwardRef(NextComposed)

Personally I think it is confusing having NextComposed being both a constant and a function, but that achieves the goal if dev tools are higher priority.

@Janpot
Copy link
Member

Janpot commented Jul 12, 2019

@virzak note #16583

@virzak
Copy link
Contributor Author

virzak commented Jul 12, 2019

[email protected] now exposes LinkProps zeit/next.js#7905

Thanks for the tip. Using this now. Had to drop the Next.js href property because it was conflicting with MUI Link which uses the underlying AnchorHTMLAttributes

@oliviertassinari oliviertassinari added the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label Jul 13, 2019
@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 15, 2019

@virzak Could you remove the usage of React.FunctionComponent from the pull request (and use named function instead)? Thanks :)

<a ref={ref} {...other} />
</NextLink>
);
});

interface LinkProps extends MuiLinkProps, NextLinkProps {
type LinkProps = LinkPropsBase & Pick<TypographyProps, 'align' | 'color' | 'display' | 'variant'>;
Copy link
Member

@oliviertassinari oliviertassinari Jul 15, 2019

Choose a reason for hiding this comment

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

What about the other props of the Link component? variantMapping, noWrap, gutterBottom and underline?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added all of the missing properties. Not sure if there can be a better solution to & {underline?: 'none' | 'hover' | 'always'};

Should there be a exported prop type for Link that includes underline?

https://github.com/mui-org/material-ui/blob/b198da072707eb6da1b5579b35eba989e26a6be4/packages/material-ui/src/Link/Link.d.ts#L9

Copy link
Member

Choose a reason for hiding this comment

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

I have tried to make an alternative implementation leveraging LinkProps without any success. Would using this type be more future proof?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, just to avoid defining it again. I guess it is what it is at this time.

@virzak
Copy link
Contributor Author

virzak commented Jul 16, 2019

@virzak note #16583

@Janpot thanks, take a look. I think the PRs are similar now.

@oliviertassinari oliviertassinari removed the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label Jul 16, 2019
@eps1lon eps1lon changed the title [example] Remove React.Ref<any> from nextjs-with-typescript example [docs] Remove React.Ref<any> from nextjs-with-typescript example Jul 17, 2019
@eps1lon eps1lon merged commit e7ac9cb into mui:master Jul 17, 2019
@eps1lon eps1lon changed the title [docs] Remove React.Ref<any> from nextjs-with-typescript example [docs] Remove <any> from nextjs-with-typescript example Jul 17, 2019
@eps1lon
Copy link
Member

eps1lon commented Jul 17, 2019

@virzak Thank you for working on this. Much appreciated.

@virzak
Copy link
Contributor Author

virzak commented Jul 17, 2019

@virzak Thank you for working on this. Much appreciated.

@eps1lon happy to help. Awesome library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to the documentation typescript
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants