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

Add TypeScript typings for TabsConfigsType. #18

Closed
nandorojo opened this issue Apr 21, 2020 · 6 comments · Fixed by #20 or #34 · May be fixed by nandorojo/react-native-animated-tabbar#1
Closed

Add TypeScript typings for TabsConfigsType. #18

nandorojo opened this issue Apr 21, 2020 · 6 comments · Fixed by #20 or #34 · May be fixed by nandorojo/react-native-animated-tabbar#1
Labels
enhancement New feature or request

Comments

@nandorojo
Copy link
Contributor

nandorojo commented Apr 21, 2020

Awesome library. I'm happy to make a PR for this, if you're open to publishing it.

Feature Request

The default tabs object looks like this:

const tabs: TabsConfigsType = {
  Home: {
    labelStyle: {
      color: '#5B37B7',
    },
    icon: {
      component: () => null,
      activeColor: 'rgba(91,55,183,1)',
      inactiveColor: 'rgba(0,0,0,1)',
    },
    background: {
      activeColor: 'rgba(223,215,243,1)',
      inactiveColor: 'rgba(223,215,243,0)',
    },
  },
  Profile: {
    labelStyle: {
      color: '#1194AA',
    },
    icon: {
      component: () => null,
      activeColor: 'rgba(17,148,170,1)',
      inactiveColor: 'rgba(0,0,0,1)',
    },
    background: {
      activeColor: 'rgba(207,235,239,1)',
      inactiveColor: 'rgba(207,235,239,0)',
    },
  },
}

The keys, Home and Profile, could be any strings. I think this should be changed to be the keys of the tabs. This could be implemented by pulling the types passed to the createBottomTabNavigator.

Why it is needed

Prevent this error from happening, due to unclear types:

IMG_526844E00DAD-1

Possible implementation

In src/types.ts, this line defines the type for the dictionary:

export interface TabsConfigsType {
  [key: string]: TabConfigsType;
}

I think the goal should be to let you optionally pass your React Navigation ParamList type as an argument.

For example, if your Tab looks like this:

type Params = {
  party: undefined
  account: undefined
}
const Tab = createBottomTabNavigator<Params>()

...then you should be able to pass Params as an argument to TabsConfigsType.

Proposed solution

Change this:

export interface TabsConfigsType {
  [key: string]: TabConfigsType;
}

To this:

export type TabsConfigsType<
  T = { [key: string]: TabConfigsType },
  K extends keyof T = keyof T
> = {
  [key in K]: TabConfigsType
}

The first generic, T = { [key: string]: TabConfigsType } is optional, since it has a default value. That default value is equal to the current type. If you don't provide a param list argument, then it will fall back to this.

The second generic, K extends keyof T = keyof T, extracts the keys. Say your param list is like this:

type Params = {
  home: undefined
  notifications: undefined 
}

const tabs: TabsConfigsType<Params> = {
  home: {
    // ...
  }
  notifs: { // 🚨"notifs" does not exist on TabsConfigsType<'home' | 'notifications'>
    // ...
  }
}

Meanwhile, if you don't pass a generic, it will work normally:

type Params = {
  home: undefined
  notifications: undefined 
}

// no errors 😇
const tabs: TabsConfigsType = {
  home: {
    // ...
  }
  notifs: { 
    // ...
  }
}

I changed it to a type, because the TypeScript interface doesn't support extracting a key from a union ([key in K]: TabConfigsType isn't possible in an interface).

Code sample

import React from 'react'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import AnimatedTabBar from '@gorhom/animated-tabbar'

interface TabConfigsType {
  labelStyle: TextStyle
  icon: {
    component:
      | ((props: {
          color: Animated.Node<string | number>
          size: number
        }) => React.ReactNode)
      | React.ReactNode
    activeColor: string
    inactiveColor: string
  }
  background: {
    activeColor: string
    inactiveColor: string
  }
}
type TabsConfigsType<
  T = { [key: string]: TabConfigsType },
  K extends keyof T = keyof T
> = {
  [key in K]: TabConfigsType
}

const tabs: TabsConfigsType<MainTabsParams> = {
  party: {
    labelStyle: {
      color: '#5B37B7',
    },
    icon: {
      component: () => null,
      activeColor: 'rgba(91,55,183,1)',
      inactiveColor: 'rgba(0,0,0,1)',
    },
    background: {
      activeColor: 'rgba(223,215,243,1)',
      inactiveColor: 'rgba(223,215,243,0)',
    },
  },
  account: {
    labelStyle: {
      color: '#1194AA',
    },
    icon: {
      component: () => null,
      activeColor: 'rgba(17,148,170,1)',
      inactiveColor: 'rgba(0,0,0,1)',
    },
    background: {
      activeColor: 'rgba(207,235,239,1)',
      inactiveColor: 'rgba(207,235,239,0)',
    },
  },
}

type MainTabsParams = {
  party: undefined
  account: undefined
}

const Tab = createBottomTabNavigator<MainTabsParams>()

export default function MainTabs() {
  return (
    <Tab.Navigator tabBar={props => <AnimatedTabBar tabs={tabs} {...props} />}>
      <Tab.Screen name={NavigationRoutes.party} component={Party} />
      <Tab.Screen name={NavigationRoutes.account} component={Home} />
    </Tab.Navigator>
  )
}
@nandorojo nandorojo added the enhancement New feature or request label Apr 21, 2020
@gorhom
Copy link
Owner

gorhom commented Apr 21, 2020

thanks @nandorojo for this well documented issue and possible solution. please feel free to submit a pr, i'll make sure to release it as soon as possible 😇

@nandorojo
Copy link
Contributor Author

You got it! Happy to help.

Do you know when you might be releasing other presets for the animation?

Awesome project!

@nandorojo
Copy link
Contributor Author

Submitted PR.

@gorhom
Copy link
Owner

gorhom commented Apr 21, 2020

Thanks mate,

for the next preset, i am working on a new one by Cuberto, hopefully by this weekend

@gorhom
Copy link
Owner

gorhom commented Apr 21, 2020

@nandorojo could you please point your PR to this repository :)

@nandorojo
Copy link
Contributor Author

Done 🙃

@gorhom gorhom linked a pull request May 9, 2020 that will close this issue
@gorhom gorhom closed this as completed in #34 May 9, 2020
gorhom added a commit that referenced this issue May 9, 2020
* Add TypeScript typings for TabsConfigsType

Close #18

* chore: updated TabsConfig

Co-authored-by: Fernando Rojo <frojo@sas.upenn.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
2 participants