How is this type annotation working in React code without TypeScript?

I was looking at this code example on the ReactRouter page, and this piece is interesting:

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      fakeAuth.isAuthenticated ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

The component: Component part looks like a type annotation. Webstorm didn't complain when I put this example into an empty file, but I didn't see them using Flow or TypeScript or anything in the imports.

Does JavaScript have Type Annotation already? I didn't see anything on MDN about this when I searched, and also React doesn't automatically provide type annotation either from what I learned...


Solution 1:

What you are seeing is not a type annotation, but a property in an object pattern. Let's simplify your example to help see what is going on.

Here's a function that is easy to understand:

f = (h) => [h.x, h.y]

The function f takes in an object h and returns an array with h.x and h.y. Now in modern JavaScript one does not have to pass in an object and break it all apart in the function body. Instead, we make the parameter section of the function be a pattern so that we don't need to bother with that h variable at all. So we could rewrite it like this (in a way that parallels your example):

f = ({x: xValue, y: yValue}) => [xValue, yValue]

So, exactly like before, you can pass to f any object that has x and y properties and it will return an array of the values at those properties.

Here it is in action:

> f = (h) => [h.x, h.y]
[Function: f]
> f({x:1, y:2, z:3})
[ 1, 2 ]
> f = ({x: xValue, y: yValue}) => [xValue, yValue]
[Function: f]
> f({x:1, y:2, z:3})
[ 1, 2 ]

As an aside, normally one would skip the xValue and yValue part and have:

f = ({x: x, y: y}) => [x, y]

which due to shorthand property notation is just:

f = ({x, y}) => [x, y]

but as @BhojendraRauniyar writes in another answer, there are capitalization conventions in the framework this code is being used with.

Solution 2:

It's not a type annotation. It's a ES6 feature called destructuring rest parameters:

First consider this example: (destructuring assignment)

const test = myObject.prop
// prop can be assigned in a variable
const { prop } = myObject
// but we want prop as a test variable
// and can be written as
const { prop: test } = myObject
// which is similar to first line
console.log(test)

This is how we can pass in the parameters:

({ component, ...rest })

// We're giving component name as Component

({ component: Component, ...rest })

So, that you can use <Component /> as you know lowercase component <component /> is invalid in react.


Furthermore, I would suggest you to deep dive into the following blogs:

Hackernoon: Understanding the destructuring assignment

JavaScript Info: Destructuring assignment

Codeburst: Destructuring assignment the complete guide

Dev.to: Destructuring assignment - array

Dev.to: Destructuring assignment - object