我正在使用一个提供工厂方法的库,另一个提供了可以与工厂方法一起使用的功能的库。
import styled from '@emotion/styled'
import shouldForwardProp from '@styled-system/should-forward-prop'
const Main = styled('main', {
shouldForwardProp
})<MainStyleProps>(compose(layout, space))
在我的代码库中,我希望对所有内容都使用此组合,并希望创建一个默认使用shouldForwardProp
中的@styled-system/should-forward-prop
的新工厂。
在普通JS中,它很简单:
import emotionStyled from '@emotion/styled'
import styledSystemShouldForwardProp from '@styled-system/should-forward-prop'
export const styled =
(tag, options) =>
emotionStyled(tag, { shouldForwardProp: styledSystemShouldForwardProp, ...options})
尽管如此,对于TS,我无法正确输入styled
函数周围的内容。默认情况下,其键入为:
export interface BaseCreateStyled<Theme extends object = any> {
<Tag extends React.ComponentType<any>, ExtraProps = {}>(
tag: Tag,
options?: StyledOptions
): CreateStyledComponentExtrinsic<Tag, ExtraProps, Theme>
<Tag extends keyof JSX.IntrinsicElements, ExtraProps = {}>(
tag: Tag,
options?: StyledOptions
): CreateStyledComponentIntrinsic<Tag, ExtraProps, Theme>
}
export interface StyledTags<Theme extends object> {
a: CreateStyledComponentIntrinsic<'a', {}, Theme>
/*
* ...all the other standard & SVG tag mappings...
*/
}
export interface CreateStyled<Theme extends object = any>
extends BaseCreateStyled<Theme>,
StyledTags<Theme> {}
declare const styled: CreateStyled
export default styled
我缺乏使嵌套条件类型起作用的技能。
我可以为JSX.IntrinsicElements
管理一个,也可以为ComponentType<any>
管理一个(非常简单),但不能同时管理两者:
import { ComponentType } from 'react'
import emotionStyled, { StyledOptions } from '@emotion/styled'
import styledSystemShouldForwardProp from '@styled-system/should-forward-prop'
/*
* This works, but does not accept styledIntrinsic(CustomReactComponent)
*/
export const styledIntrinsic =
(tag: keyof JSX.IntrinsicElements, options?: StyledOptions) =>
emotionStyled(tag, { shouldForwardProp: styledSystemShouldForwardProp, ...options })
/*
* This works, but does not accept styledComponentType('main')
*/
export const styledComponentType =
(tag: ComponentType<any>, options?: StyledOptions) =>
emotionStyled(tag, { shouldForwardProp: styledSystemShouldForwardProp, ...options })
/*
* This one produces a static typing error.
*/
export const styledMerged =
(tag: ComponentType<any> | keyof JSX.IntrinsicElements, options?: StyledOptions) =>
emotionStyled(tag, { shouldForwardProp: styledSystemShouldForwardProp, ...options })
错误为:
Argument of type '"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 154 more ... | FunctionComponent<...>' is not assignable to parameter of type '"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 152 more ... | "view"'.
Type 'ComponentClass<any, any>' is not assignable to type '"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 152 more ... | "view"'.
Type 'ComponentClass<any, any>' is not assignable to type '"view"'.ts(2345)
我也尝试过定义自定义界面,但无济于事。显然,我的打字稿技能只有这么远。
如何使我期望的功能也遵循styled
的输入?
链接到CodeSandbox:https://codesandbox.io/s/shy-brook-59rdz
我设法使用以下方法来解决问题:
export const styled: BaseCreateStyled = (tag, options?) =>
emotionStyled(tag, { shouldForwardProp: styledSystemShouldForwardProp, ...options })
它可以正常工作!,但是感觉很不客气,因为将tag
和options
参数推断为any
。
另外,引起骇客的是我正在使用BaseCreateStyled
,因为它不适用于最终类型的CreateStyled
:
export const styled: CreateStyled = (tag, options?) =>
emotionStyled(tag, { shouldForwardProp: styledSystemShouldForwardProp, ...options })
错误:
Type '(tag: any, options?: any) => CreateStyledComponentBaseThemeless<any, {}>' is missing the following properties from type 'CreateStyled<any>': a, abbr, address, area, and 129 more.ts(2740)
链接到CodeSandbox的分支:https://codesandbox.io/s/awesome-pike-ug7jh