diff --git a/docs/typescript.mdx b/docs/typescript.mdx index 7abd6a0680..645609aafd 100644 --- a/docs/typescript.mdx +++ b/docs/typescript.mdx @@ -236,7 +236,8 @@ However, you can define a theme type by creating another `styled` instance. _styled.tsx_ ```tsx -import styled, { CreateStyled } from '@emotion/styled' +import styled from '@emotion/styled' +import { CreateThemedStyled } from 'emotion-theming' type Theme = { color: { @@ -247,7 +248,7 @@ type Theme = { // ... } -export default styled as CreateStyled +export default styled as CreateThemedStyled ``` _Button.tsx_ diff --git a/packages/emotion-theming/types/index.d.ts b/packages/emotion-theming/types/index.d.ts index 2cd13a1204..9108e59a49 100644 --- a/packages/emotion-theming/types/index.d.ts +++ b/packages/emotion-theming/types/index.d.ts @@ -3,7 +3,11 @@ import * as React from 'react' -import { AddOptionalTo, PropsOf } from './helper' +import { + StyledComponent, + StyledOptions, + CreateStyledComponent +} from '@emotion/styled' export interface ThemeProviderProps { theme: Partial | ((outerTheme: Theme) => Theme) @@ -14,17 +18,43 @@ export function ThemeProvider( props: ThemeProviderProps ): React.ReactElement -/** - * @todo Add more constraint to C so that - * this function only accepts components with theme props. - */ -export function withTheme>( - component: C -): React.SFC, 'theme'>> +export function withTheme

( + component: React.ComponentType

+): // Return type needs to have an optional theme so it is composible +React.FC & { theme?: any }> export interface EmotionTheming { ThemeProvider(props: ThemeProviderProps): React.ReactElement - withTheme>( - component: C - ): React.SFC, 'theme'>> + withTheme

( + component: React.ComponentType

+ ): React.FC & { theme?: any }> +} + +/** + * @desc + * This function accepts `InnerProps`/`Tag` to infer the type of `tag`, + * and accepts `ExtraProps` for user who use string style + * to be able to declare extra props without using + * `` styled('button')`...` ``, which does not supported in + * styled-component VSCode extension. + * If your tool support syntax highlighting for `` styled('button')`...` `` + * it could be more efficient. + */ +export interface CreateThemedStyled { + ( + tag: React.ComponentType, + options?: StyledOptions + ): CreateStyledComponent + + ( + tag: Tag, + options?: StyledOptions + ): CreateStyledComponent< + JSX.IntrinsicElements[Tag], + ExtraProps & { theme: Theme } + > } + +export type WithTheme = P extends { theme: infer Theme } + ? P & { theme: Exclude } + : P & { theme: T } diff --git a/packages/serialize/types/index.d.ts b/packages/serialize/types/index.d.ts index e4f58419f5..56893e1fc6 100644 --- a/packages/serialize/types/index.d.ts +++ b/packages/serialize/types/index.d.ts @@ -4,8 +4,6 @@ import { RegisteredCache, SerializedStyles } from '@emotion/utils' import * as CSS from 'csstype' -import { Equal } from './helper' - export { RegisteredCache, SerializedStyles } export type CSSProperties = CSS.PropertiesFallback @@ -63,7 +61,19 @@ export interface ObjectInterpolation extends CSSPropertiesWithMultiValues, CSSPseudos, CSSOthersObject {} -export type FunctionInterpolation = (mergedProps: MP) => Interpolation +export interface FunctionInterpolation { + (mergedProps: MP): + | null + | undefined + | boolean + | number + | string + | ComponentSelector + | Keyframes + | SerializedStyles + | ArrayInterpolation + | ObjectInterpolation +} export type Interpolation = | null @@ -76,7 +86,7 @@ export type Interpolation = | SerializedStyles | ArrayInterpolation | ObjectInterpolation - | Equal> + | FunctionInterpolation export function serializeStyles( args: Array>, diff --git a/packages/styled-base/types/index.d.ts b/packages/styled-base/types/index.d.ts index 52dfe2fb3e..83530dc62b 100644 --- a/packages/styled-base/types/index.d.ts +++ b/packages/styled-base/types/index.d.ts @@ -15,8 +15,6 @@ import { ComponentSelector, Interpolation } from '@emotion/serialize' import * as React from 'react' -import { Omit, Overwrapped, PropsOf } from './helper' - export { ArrayInterpolation, CSSObject, @@ -26,105 +24,38 @@ export { export { ComponentSelector, Interpolation } -type JSXInEl = JSX.IntrinsicElements - -export type WithTheme = P extends { theme: infer Theme } - ? P & { theme: Exclude } - : P & { theme: T } - export interface StyledOptions { label?: string shouldForwardProp?(propName: string): boolean target?: string } -export interface StyledComponent - extends React.SFC, +export interface StyledComponent + extends React.SFC, ComponentSelector { /** * @desc this method is type-unsafe */ - withComponent( + withComponent( tag: NewTag - ): StyledComponent - withComponent>( - tag: Tag - ): StyledComponent, StyleProps, Theme> + ): StyledComponent + withComponent( + tag: React.ComponentType + ): StyledComponent } type ReactClassPropKeys = keyof React.ClassAttributes -interface CreateStyledComponentBaseThemeless { - < - StyleProps extends Omit< - Overwrapped, - ReactClassPropKeys - > = Omit, - Theme extends object = object - >( - ...styles: Array>> - ): StyledComponent - < - StyleProps extends Omit< - Overwrapped, - ReactClassPropKeys - > = Omit, - Theme extends object = object - >( +export interface CreateStyledComponent { + ( + ...styles: Array> + ): StyledComponent + ( template: TemplateStringsArray, - ...styles: Array>> - ): StyledComponent + ...styles: Array> + ): StyledComponent } -interface CreateStyledComponentBaseThemed< - InnerProps, - ExtraProps, - StyledInstanceTheme extends object -> { - < - StyleProps extends Omit< - Overwrapped, - ReactClassPropKeys - > = Omit - >( - ...styles: Array>> - ): StyledComponent - < - StyleProps extends Omit< - Overwrapped, - ReactClassPropKeys - > = Omit - >( - template: TemplateStringsArray, - ...styles: Array>> - ): StyledComponent -} - -export type CreateStyledComponentBase< - InnerProps, - ExtraProps, - StyledInstanceTheme extends object -> = - // this "reversed" condition checks if StyledInstanceTheme was already parametrized when using CreateStyled - object extends StyledInstanceTheme - ? CreateStyledComponentBaseThemeless - : CreateStyledComponentBaseThemed< - InnerProps, - ExtraProps, - StyledInstanceTheme - > - -export type CreateStyledComponentIntrinsic< - Tag extends keyof JSXInEl, - ExtraProps, - Theme extends object -> = CreateStyledComponentBase -export type CreateStyledComponentExtrinsic< - Tag extends React.ComponentType, - ExtraProps, - Theme extends object -> = CreateStyledComponentBase, ExtraProps, Theme> - /** * @desc * This function accepts `InnerProps`/`Tag` to infer the type of `tag`, @@ -135,16 +66,16 @@ export type CreateStyledComponentExtrinsic< * If your tool support syntax highlighting for `` styled('button')`...` `` * it could be more efficient. */ -export interface CreateStyled { - , ExtraProps = {}>( - tag: Tag, +export interface CreateStyled { + ( + component: React.ComponentType, options?: StyledOptions - ): CreateStyledComponentExtrinsic + ): CreateStyledComponent - ( + ( tag: Tag, options?: StyledOptions - ): CreateStyledComponentIntrinsic + ): CreateStyledComponent } declare const styled: CreateStyled diff --git a/packages/styled/types/index.d.ts b/packages/styled/types/index.d.ts index 14347014f6..288eb10e99 100644 --- a/packages/styled/types/index.d.ts +++ b/packages/styled/types/index.d.ts @@ -3,177 +3,29 @@ import { CreateStyled as BaseCreateStyled, - CreateStyledComponentIntrinsic + CreateStyledComponent } from '@emotion/styled-base' export { ArrayInterpolation, ComponentSelector, - CreateStyledComponentBase, - CreateStyledComponentExtrinsic, - CreateStyledComponentIntrinsic, CSSObject, FunctionInterpolation, Interpolation, ObjectInterpolation, StyledComponent, StyledOptions, - WithTheme + CreateStyledComponent } from '@emotion/styled-base' -export interface StyledTags { - /** - * @desc - * HTML tags - */ - a: CreateStyledComponentIntrinsic<'a', {}, Theme> - abbr: CreateStyledComponentIntrinsic<'abbr', {}, Theme> - address: CreateStyledComponentIntrinsic<'address', {}, Theme> - area: CreateStyledComponentIntrinsic<'area', {}, Theme> - article: CreateStyledComponentIntrinsic<'article', {}, Theme> - aside: CreateStyledComponentIntrinsic<'aside', {}, Theme> - audio: CreateStyledComponentIntrinsic<'audio', {}, Theme> - b: CreateStyledComponentIntrinsic<'b', {}, Theme> - base: CreateStyledComponentIntrinsic<'base', {}, Theme> - bdi: CreateStyledComponentIntrinsic<'bdi', {}, Theme> - bdo: CreateStyledComponentIntrinsic<'bdo', {}, Theme> - big: CreateStyledComponentIntrinsic<'big', {}, Theme> - blockquote: CreateStyledComponentIntrinsic<'blockquote', {}, Theme> - body: CreateStyledComponentIntrinsic<'body', {}, Theme> - br: CreateStyledComponentIntrinsic<'br', {}, Theme> - button: CreateStyledComponentIntrinsic<'button', {}, Theme> - canvas: CreateStyledComponentIntrinsic<'canvas', {}, Theme> - caption: CreateStyledComponentIntrinsic<'caption', {}, Theme> - cite: CreateStyledComponentIntrinsic<'cite', {}, Theme> - code: CreateStyledComponentIntrinsic<'code', {}, Theme> - col: CreateStyledComponentIntrinsic<'col', {}, Theme> - colgroup: CreateStyledComponentIntrinsic<'colgroup', {}, Theme> - data: CreateStyledComponentIntrinsic<'data', {}, Theme> - datalist: CreateStyledComponentIntrinsic<'datalist', {}, Theme> - dd: CreateStyledComponentIntrinsic<'dd', {}, Theme> - del: CreateStyledComponentIntrinsic<'del', {}, Theme> - details: CreateStyledComponentIntrinsic<'details', {}, Theme> - dfn: CreateStyledComponentIntrinsic<'dfn', {}, Theme> - dialog: CreateStyledComponentIntrinsic<'dialog', {}, Theme> - div: CreateStyledComponentIntrinsic<'div', {}, Theme> - dl: CreateStyledComponentIntrinsic<'dl', {}, Theme> - dt: CreateStyledComponentIntrinsic<'dt', {}, Theme> - em: CreateStyledComponentIntrinsic<'em', {}, Theme> - embed: CreateStyledComponentIntrinsic<'embed', {}, Theme> - fieldset: CreateStyledComponentIntrinsic<'fieldset', {}, Theme> - figcaption: CreateStyledComponentIntrinsic<'figcaption', {}, Theme> - figure: CreateStyledComponentIntrinsic<'figure', {}, Theme> - footer: CreateStyledComponentIntrinsic<'footer', {}, Theme> - form: CreateStyledComponentIntrinsic<'form', {}, Theme> - h1: CreateStyledComponentIntrinsic<'h1', {}, Theme> - h2: CreateStyledComponentIntrinsic<'h2', {}, Theme> - h3: CreateStyledComponentIntrinsic<'h3', {}, Theme> - h4: CreateStyledComponentIntrinsic<'h4', {}, Theme> - h5: CreateStyledComponentIntrinsic<'h5', {}, Theme> - h6: CreateStyledComponentIntrinsic<'h6', {}, Theme> - head: CreateStyledComponentIntrinsic<'head', {}, Theme> - header: CreateStyledComponentIntrinsic<'header', {}, Theme> - hgroup: CreateStyledComponentIntrinsic<'hgroup', {}, Theme> - hr: CreateStyledComponentIntrinsic<'hr', {}, Theme> - html: CreateStyledComponentIntrinsic<'html', {}, Theme> - i: CreateStyledComponentIntrinsic<'i', {}, Theme> - iframe: CreateStyledComponentIntrinsic<'iframe', {}, Theme> - img: CreateStyledComponentIntrinsic<'img', {}, Theme> - input: CreateStyledComponentIntrinsic<'input', {}, Theme> - ins: CreateStyledComponentIntrinsic<'ins', {}, Theme> - kbd: CreateStyledComponentIntrinsic<'kbd', {}, Theme> - keygen: CreateStyledComponentIntrinsic<'keygen', {}, Theme> - label: CreateStyledComponentIntrinsic<'label', {}, Theme> - legend: CreateStyledComponentIntrinsic<'legend', {}, Theme> - li: CreateStyledComponentIntrinsic<'li', {}, Theme> - link: CreateStyledComponentIntrinsic<'link', {}, Theme> - main: CreateStyledComponentIntrinsic<'main', {}, Theme> - map: CreateStyledComponentIntrinsic<'map', {}, Theme> - mark: CreateStyledComponentIntrinsic<'mark', {}, Theme> - /** - * @desc - * marquee tag is not supported by @types/react - */ - // 'marquee': CreateStyledComponentIntrinsic<'marquee', {}, Theme>; - menu: CreateStyledComponentIntrinsic<'menu', {}, Theme> - menuitem: CreateStyledComponentIntrinsic<'menuitem', {}, Theme> - meta: CreateStyledComponentIntrinsic<'meta', {}, Theme> - meter: CreateStyledComponentIntrinsic<'meter', {}, Theme> - nav: CreateStyledComponentIntrinsic<'nav', {}, Theme> - noscript: CreateStyledComponentIntrinsic<'noscript', {}, Theme> - object: CreateStyledComponentIntrinsic<'object', {}, Theme> - ol: CreateStyledComponentIntrinsic<'ol', {}, Theme> - optgroup: CreateStyledComponentIntrinsic<'optgroup', {}, Theme> - option: CreateStyledComponentIntrinsic<'option', {}, Theme> - output: CreateStyledComponentIntrinsic<'output', {}, Theme> - p: CreateStyledComponentIntrinsic<'p', {}, Theme> - param: CreateStyledComponentIntrinsic<'param', {}, Theme> - picture: CreateStyledComponentIntrinsic<'picture', {}, Theme> - pre: CreateStyledComponentIntrinsic<'pre', {}, Theme> - progress: CreateStyledComponentIntrinsic<'progress', {}, Theme> - q: CreateStyledComponentIntrinsic<'q', {}, Theme> - rp: CreateStyledComponentIntrinsic<'rp', {}, Theme> - rt: CreateStyledComponentIntrinsic<'rt', {}, Theme> - ruby: CreateStyledComponentIntrinsic<'ruby', {}, Theme> - s: CreateStyledComponentIntrinsic<'s', {}, Theme> - samp: CreateStyledComponentIntrinsic<'samp', {}, Theme> - script: CreateStyledComponentIntrinsic<'script', {}, Theme> - section: CreateStyledComponentIntrinsic<'section', {}, Theme> - select: CreateStyledComponentIntrinsic<'select', {}, Theme> - small: CreateStyledComponentIntrinsic<'small', {}, Theme> - source: CreateStyledComponentIntrinsic<'source', {}, Theme> - span: CreateStyledComponentIntrinsic<'span', {}, Theme> - strong: CreateStyledComponentIntrinsic<'strong', {}, Theme> - style: CreateStyledComponentIntrinsic<'style', {}, Theme> - sub: CreateStyledComponentIntrinsic<'sub', {}, Theme> - summary: CreateStyledComponentIntrinsic<'summary', {}, Theme> - sup: CreateStyledComponentIntrinsic<'sup', {}, Theme> - table: CreateStyledComponentIntrinsic<'table', {}, Theme> - tbody: CreateStyledComponentIntrinsic<'tbody', {}, Theme> - td: CreateStyledComponentIntrinsic<'td', {}, Theme> - textarea: CreateStyledComponentIntrinsic<'textarea', {}, Theme> - tfoot: CreateStyledComponentIntrinsic<'tfoot', {}, Theme> - th: CreateStyledComponentIntrinsic<'th', {}, Theme> - thead: CreateStyledComponentIntrinsic<'thead', {}, Theme> - time: CreateStyledComponentIntrinsic<'time', {}, Theme> - title: CreateStyledComponentIntrinsic<'title', {}, Theme> - tr: CreateStyledComponentIntrinsic<'tr', {}, Theme> - track: CreateStyledComponentIntrinsic<'track', {}, Theme> - u: CreateStyledComponentIntrinsic<'u', {}, Theme> - ul: CreateStyledComponentIntrinsic<'ul', {}, Theme> - var: CreateStyledComponentIntrinsic<'var', {}, Theme> - video: CreateStyledComponentIntrinsic<'video', {}, Theme> - wbr: CreateStyledComponentIntrinsic<'wbr', {}, Theme> - - /** - * @desc - * SVG tags - */ - circle: CreateStyledComponentIntrinsic<'circle', {}, Theme> - clipPath: CreateStyledComponentIntrinsic<'clipPath', {}, Theme> - defs: CreateStyledComponentIntrinsic<'defs', {}, Theme> - ellipse: CreateStyledComponentIntrinsic<'ellipse', {}, Theme> - foreignObject: CreateStyledComponentIntrinsic<'foreignObject', {}, Theme> - g: CreateStyledComponentIntrinsic<'g', {}, Theme> - image: CreateStyledComponentIntrinsic<'image', {}, Theme> - line: CreateStyledComponentIntrinsic<'line', {}, Theme> - linearGradient: CreateStyledComponentIntrinsic<'linearGradient', {}, Theme> - mask: CreateStyledComponentIntrinsic<'mask', {}, Theme> - path: CreateStyledComponentIntrinsic<'path', {}, Theme> - pattern: CreateStyledComponentIntrinsic<'pattern', {}, Theme> - polygon: CreateStyledComponentIntrinsic<'polygon', {}, Theme> - polyline: CreateStyledComponentIntrinsic<'polyline', {}, Theme> - radialGradient: CreateStyledComponentIntrinsic<'radialGradient', {}, Theme> - rect: CreateStyledComponentIntrinsic<'rect', {}, Theme> - stop: CreateStyledComponentIntrinsic<'stop', {}, Theme> - svg: CreateStyledComponentIntrinsic<'svg', {}, Theme> - text: CreateStyledComponentIntrinsic<'text', {}, Theme> - tspan: CreateStyledComponentIntrinsic<'tspan', {}, Theme> +export type StyledTags = { + [tag in keyof JSX.IntrinsicElements]: CreateStyledComponent< + JSX.IntrinsicElements[tag], + ExtraProps + > } -export interface CreateStyled - extends BaseCreateStyled, - StyledTags {} +export interface CreateStyled extends BaseCreateStyled, StyledTags {} declare const styled: CreateStyled export default styled