合并嵌套条件类型以作为一个参数传递

时间:2019-08-08 12:18:29

标签: reactjs typescript emotion

我正在使用一个提供工厂方法的库,另一个提供了可以与工厂方法一起使用的功能的库。

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 })

它可以正常工作!,但是感觉很不客气,因为将tagoptions参数推断为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

0 个答案:

没有答案