Débutant TypeScript ici. J'ai un composant ci-dessous utilisant styled-components
que je voudrais convertir en TypeScript
.
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
const propTypes = {
name: PropTypes.string.isRequired // https://material.io/tools/icons/?style=baseline
}
const Icon = styled(({name, className, ...props}) => <i className={`material-icons ${className}`} {...props}>{name}</i>)`
font-size: ${props => props.theme.sizeLarger};
`
Icon.propTypes = propTypes
export default Icon
Je sais que je peux remplacer mon propTypes
par un interface
interface Props {
name: string
}
Cependant, TypeScript se plaint que je laisse className
non déclaré. Le truc c'est que j'aimerais idéalement utiliser le interface
comme une sorte de spécification pour les accessoires qu'un développeur peut fournir, sans avoir à déclarer des accessoires comme className
ou theme
qui sont injectés par des bibliothèques comme styled-components
.
Comment convertir correctement ce composant en TypeScript?
Voici une approche complète utilisant Styled Components v5 avec React Native qui fonctionnera également avec plain React également. Si vous n'utilisez pas de thème, vous pouvez passer à la section StyledProps
en bas.
Définissez votre type de thème.
// MyTheme.ts
export type MyTheme = {
colors: {
primary: string;
background: string;
};
};
Utilisez le type sur vos thèmes.
// themes.ts
export const LightTheme: MyTheme = {
colors: {
primary: 'white',
background: 'white',
},
};
export const DarkTheme: MyTheme = {
colors: {
primary: 'grey',
background: 'black',
},
};
Utilisez fusion de déclaration pour "fusionner" le type MyTheme dans le thème par défaut des composants stylisés.
// styled.d.ts
import 'styled-components';
import { MyTheme } from '../src/themes/MyTheme';
declare module 'styled-components' {
// eslint-disable-next-line @TypeScript-eslint/no-empty-interface
export interface DefaultTheme extends MyTheme {}
}
OK cool. Le prop theme
est correctement tapé.
Qu'en est-il des composants eux-mêmes?
Enveloppez vos accessoires de composant spécifiques dans le type StyledProps
.
import { StyledProps } from 'styled-components';
import styled from 'styled-components/native';
type MyViewProps = StyledProps<{
backgroundColor?: string;
isAlert?: boolean;
}>;
const MyView = styled.View(
(props: MyViewProps) => `
background-color: ${props.backgroundColor || props.theme.colors.background};
color: ${props.isAlert ? red : props.theme.colors.primary}
`,
);
Dans cet exemple, les deux props.backgroundColor
et props.theme.colors.background
se terminera automatiquement. Lorsque vous mettez à jour le type MyTheme
ou le type de composant spécifique, cela devrait simplement fonctionner. ????