reactjs - Slå fast Prop-grensesnitt fra styled-component
Jeg prøver å utlede komponentenes Props-grensesnitt i stedet for å eksportere dem når det er mulig. Dette er ikke et problem med klasse- og funksjonskomponenter, men hvis jeg prøver å utlede Props-grensesnittet til en styled-component, blir prop-en typet til any, noe som ikke er ideelt.
interface Props {
bgColor: string;
children: React.ReactNode;
}
const Box = styled.div<Props>`
background-color: ${(p) => p.bgColor};
`;
const Button = (props: Props) => (
<button style={{ backgroundColor: props.bgColor }}>{props.children}</button>
);
type ButtonInferredProps = React.ComponentProps<typeof Button>;
type BoxInferredProps = React.ComponentProps<typeof Box>;
const OtherBox = (props: BoxInferredProps) => (
<div style={{ backgroundColor: props.bgColor }}>{props.children}</div>
);
const OtherButton = (props: ButtonInferredProps) => (
<button style={{ backgroundColor: props.bgColor }}>{props.children}</button>
);
export default function App() {
return (
<>
<Box bgColor="red">Hi! I'm a box! </Box>
<OtherBox bgColor="purple" backgroundColor="red">
Hi! I'm another box
</OtherBox>
<Button bgColor="blue">Hi! I'm a button</Button>
<OtherButton bgColor="green">Hi! I'm another button</OtherButton>
</>
);
}
Med Box som en styled-component, kan jeg ikke riktig fastslå dens Props-grensesnitt. Når jeg lager en annen komponent som forsøker å bruke den utledede Props-typen, blir den som any:
const OtherBox = (props: BoxInferredProps) => (
{/* TS won't complain that `props` doesn't have a `iAmNotTyped` property which is desired... */}
<div style={{ backgroundColor: props.iAmNotTyped}}>{props.children}</div>
);
https://codesandbox.io/s/styled-components-typescript-forked-7cq4q?file=/src/App.tsx
Svar #1
styled-components eksporterer en Typescript-hjelper for dette.
Det kalles StyledComponentPropsWithRef:
import React from 'react';
import styled, { StyledComponentPropsWithRef } from 'styled-components';
const RedLink = styled.a`
color: red;
`;
type Props = StyledComponentPropsWithRef<typeof RedLink>;
const Link = (props: Props) => <RedLink {...props} />;
export default function App() {
return <Link href="/" role="button" />;
}
Denne koden fungerer ☝️
Svar #2
Typen for din Box-stilkomponent vises som StyledComponent<"div", any, Props, never>. Så du kan bruke TypeScripts infer-nøkkelord for å hente ut Props fra den typedefinisjonen.
import {StyledComponent} from "styled-components";
type StyledComponentProps<T> = T extends StyledComponent<any, any, infer P, any> ? P : never
type BoxInferredProps = StyledComponentProps<typeof Box>;
Nå får du en TypeScript-feil, som forventet, når du prøver å tilordne backgroundColor på OtherBox.
