如何使用 Typescript 在不丢失任何道具的情况下键入样式组件?
Posted
技术标签:
【中文标题】如何使用 Typescript 在不丢失任何道具的情况下键入样式组件?【英文标题】:How to type a styled component without losing any prop with Typescript? 【发布时间】:2019-08-05 20:04:53 【问题描述】:我是样式化组件的新手,我希望能够正确输入样式化组件,这样当我传递“vs code”道具时,我可以自动检测我拥有的所有道具,而不仅仅是主题中的那个或者我可以用接口放置的那些。
我在其他answer 中看到的那样,如果不使用 HOC,有什么办法吗?是否有可能获得一个通用的道具来使用,而不必像示例中那样在样式的每个属性中定义?
app.theme.ts
export const theme =
palette:
primaryColor: '#FF5018',
secondaryColor: '#252729',
tertiaryColor: '#1A1C1E',
textColor: 'white',
,
;
export type Theme = typeof theme;
navigation-bar.styled.component.ts
export const NavigationBarStyled = styled.div`
grid-area: navigation-bar-item;
padding-left: 2rem;
display: flex;
align-items: center;
color: $( theme ) => theme.palette.primaryColor;
background-color: $( theme ) => theme.palette.primaryColor;
`;
提前致谢, 最好的
【问题讨论】:
【参考方案1】:出于某种原因(可能是由于styled-components
的打字稿定义的编写方式),如果您删除其中一个嵌套级别,Theme
的打字工作。这个 sn-p 类型检查对我来说没有错误(v4),即打字稿知道primaryColor
是string
:
const theme =
primaryColor: '#FF5018',
secondaryColor: '#252729',
tertiaryColor: '#1A1C1E',
textColor: 'white',
;
type Theme = typeof theme;
type Props = Theme &
// ... other keys
const NavigationBarStyled = styled.div<Props>`
grid-area: navigation-bar-item;
padding-left: 2rem;
display: flex;
align-items: center;
color: $props => props.primaryColor;
background-color: $props => props.primaryColor;
`;
【讨论】:
嗨@Huy-Nguyen,谢谢你的回答,但是有了这个道具的实现,你不会失去关于样式化组件或反应的其他属性吗?因为您减少了仅具有主题属性或您输入的自定义属性的可能性? 还有... 是否可以一次调用附件来使用它们?提前致谢!【参考方案2】:这可以像@Huy-Nguyen 所说的那样解决,但实际上,您会丢失样式组件的属性,或者您必须多次定义相同的属性。
所以最好的选择就是 Styled-Components 网站所说的(定义主题界面):
主题.ts
export default interface ThemeInterface
primaryColor: string;
primaryColorInverted: string;
styled-components.ts
import * as styledComponents from "styled-components";
import ThemeInterface from "./theme";
const
default: styled,
css,
createGlobalStyle,
keyframes,
ThemeProvider
= styledComponents as styledComponents.ThemedStyledComponentsModule<ThemeInterface>;
export css, createGlobalStyle, keyframes, ThemeProvider ;
export default styled;
然后,你使用它:
import styled from 'app/styled-components';
// theme is now fully typed
const Title = styled.h1`
color: $props => props.theme.primaryColor;
`;
只需传递链接:https://www.styled-components.com/docs/api#define-a-theme-interface
非常感谢大家。
【讨论】:
【参考方案3】:我们采用了不同的方法。注意:带有 React Native 的 Styled Components v5
定义您的主题类型。
// MyTheme.ts
export type MyTheme =
colors:
primary: string;
background: string;
;
;
在您的主题上使用类型。
// themes.ts
export const LightTheme: MyTheme =
colors:
primary: 'white',
background: 'white',
,
;
export const DarkTheme: MyTheme =
colors:
primary: 'grey',
background: 'black',
,
;
使用 declaration merging 将 MyTheme 类型“合并”到 Styled Components 默认主题中。
// 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
好的,很酷。 theme
属性输入正确。
组件本身呢?
将您的特定组件道具包装在 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
`,
);
在此示例中,props.backgroundColor
和 props.theme.colors.background
都将自动完成。当您更新 MyTheme
类型或特定组件类型时,它应该可以正常工作。 ?
【讨论】:
我发誓这种方法一直对我有用。但是我正在处理的当前项目中的某些内容有所不同,我在props
上看到的所有类型都是any
。我唯一不同的是我使用的是StyledComponentsThemeProvider
。你有什么想法为什么我只是在道具上得到任何东西?【参考方案4】:
我不知道这是否是最好的方法。但我找到了如下解决方案。
// theme.ts
const theme =
colors:
...
;
export type themeTypes = typeof theme;
export default theme;
// styled.d.ts ( in root folder )
import 'styled-components'
import themeTypes from '@/styles/theme'
declare module 'styled-components'
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DefaultTheme extends themeTypes
【讨论】:
以上是关于如何使用 Typescript 在不丢失任何道具的情况下键入样式组件?的主要内容,如果未能解决你的问题,请参考以下文章
在没有道具的 Typescript 中使用 React.forwardRef
修复“‘组件’没有任何构造或调用签名。” Typescript 的默认道具错误
如何在传递道具时使用 TypeScript 实现“as”道具?