// forward declarations declare global { namespace NodeJS { // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ReadableStream {} } // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ShadowRoot {} } import * as CSS from "csstype"; import * as hoistNonReactStatics from "hoist-non-react-statics"; import * as React from "react"; export type CSSProperties = CSS.Properties; export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject }; export interface CSSObject extends CSSProperties, CSSPseudos { [key: string]: CSSObject | string | number | undefined; } export type CSSKeyframes = object & { [key: string]: CSSObject }; export interface ThemeProps { theme: T; } export type ThemedStyledProps = P & ThemeProps; export type StyledProps

= ThemedStyledProps>; export type IntrinsicElementsKeys = keyof JSX.IntrinsicElements; // Any prop that has a default prop becomes optional, but its type is unchanged // Undeclared default props are augmented into the resulting allowable attributes // If declared props have indexed properties, ignore default props entirely as keyof gets widened // Wrap in an outer-level conditional type to allow distribution over props that are unions type Defaultize = P extends any ? string extends keyof P ? P : & PickU> & Partial>> & Partial>> : never; type ReactDefaultizedProps = C extends { defaultProps: infer D } ? Defaultize : P; type MakeAttrsOptional< C extends string | React.ComponentType, O extends object, A extends keyof P, P = React.ComponentPropsWithRef ? C : never>, > = // Distribute unions early to avoid quadratic expansion P extends any ? OmitU & O, A> & Partial> : never; export type StyledComponentProps< // The Component from whose props are derived C extends string | React.ComponentType, // The Theme from the current context T extends object, // The other props added by the template O extends object, // The props that are made optional by .attrs A extends keyof any, // The Component passed with "forwardedAs" prop FAsC extends string | React.ComponentType = C, > = // Distribute O if O is a union type O extends object ? WithOptionalTheme< MakeAttrsOptional & MakeAttrsOptional, T > : never; type StyledComponentPropsWithAs< C extends string | React.ComponentType, T extends object, O extends object, A extends keyof any, AsC extends string | React.ComponentType = C, FAsC extends string | React.ComponentType = C, > = StyledComponentProps & { as?: AsC | undefined; forwardedAs?: FAsC | undefined }; export type FalseyValue = undefined | null | false; export type Interpolation

= InterpolationValue | InterpolationFunction

| FlattenInterpolation

; // cannot be made a self-referential interface, breaks WithPropNested // see https://github.com/microsoft/TypeScript/issues/34796 export type FlattenInterpolation

= ReadonlyArray>; export type InterpolationValue = string | number | FalseyValue | Keyframes | StyledComponentInterpolation | CSSObject; export type SimpleInterpolation = InterpolationValue | FlattenSimpleInterpolation; export type FlattenSimpleInterpolation = readonly SimpleInterpolation[]; export type InterpolationFunction

= (props: P) => Interpolation

; type Attrs, T> = ((props: ThemedStyledProps) => A) | A; export type ThemedGlobalStyledClassProps

= WithOptionalTheme & { suppressMultiMountWarning?: boolean | undefined; }; export interface GlobalStyleComponent

extends React.ComponentClass> {} // remove the call signature from StyledComponent so Interpolation can still infer InterpolationFunction type StyledComponentInterpolation = | PickU, keyof StyledComponentBase> | PickU, keyof StyledComponentBase>; // abuse Pick to strip the call signature from ForwardRefExoticComponent type ForwardRefExoticBase

= PickU, keyof React.ForwardRefExoticComponent>; // Config to be used with withConfig export interface StyledConfig { // TODO: Add all types from the original StyledComponentWrapperProperties componentId?: string; displayName?: string; shouldForwardProp?: ((prop: keyof O, defaultValidatorFn: (prop: keyof O) => boolean) => boolean) | undefined; } // extracts React defaultProps type ReactDefaultProps = C extends { defaultProps: infer D } ? D : never; // any doesn't count as assignable to never in the extends clause, and we default A to never export type AnyStyledComponent = StyledComponent | StyledComponent; export type StyledComponent< C extends keyof JSX.IntrinsicElements | React.ComponentType, T extends object, O extends object = {}, A extends keyof any = never, > = // the "string" allows this to be used as an object key // I really want to avoid this if possible but it's the only way to use nesting with object styles... & string & StyledComponentBase & hoistNonReactStatics.NonReactStatics ? C : never>; export interface StyledComponentBase< C extends string | React.ComponentType, T extends object, O extends object = {}, A extends keyof any = never, > extends ForwardRefExoticBase> { // add our own fake call signature to implement the polymorphic 'as' prop ( props: StyledComponentProps & { as?: never | undefined; forwardedAs?: never | undefined }, ): React.ReactElement< StyledComponentProps >; = C, FAsC extends string | React.ComponentType = AsC>( props: StyledComponentPropsWithAs, ): React.ReactElement>; withComponent( component: WithC, ): StyledComponent< StyledComponentInnerComponent, T, O & StyledComponentInnerOtherProps, A | StyledComponentInnerAttrs >; withComponent>( component: WithC, ): StyledComponent; } export interface ThemedStyledFunctionBase< C extends keyof JSX.IntrinsicElements | React.ComponentType, T extends object, O extends object = {}, A extends keyof any = never, > { (first: TemplateStringsArray): StyledComponent; ( first: | TemplateStringsArray | CSSObject | InterpolationFunction & O, T>>, ...rest: Array & O, T>>> ): StyledComponent; ( first: | TemplateStringsArray | CSSObject | InterpolationFunction & O & U, T>>, ...rest: Array & O & U, T>>> ): StyledComponent; } export interface ThemedStyledFunction< C extends keyof JSX.IntrinsicElements | React.ComponentType, T extends object, O extends object = {}, A extends keyof any = never, > extends ThemedStyledFunctionBase { // Fun thing: 'attrs' can also provide a polymorphic 'as' prop // My head already hurts enough so maybe later... attrs< U, NewA extends Partial & U> & { [others: string]: any; } = {}, >( attrs: Attrs & U, NewA, T>, ): ThemedStyledFunction; withConfig: ( config: StyledConfig & Props>, ) => ThemedStyledFunction; } export type StyledFunction> = ThemedStyledFunction< C, any >; type ThemedStyledComponentFactories = { [TTag in keyof JSX.IntrinsicElements]: ThemedStyledFunction; }; export type StyledComponentInnerComponent> = C extends StyledComponent< infer I, any, any, any > ? I : C extends StyledComponent ? I : C; export type StyledComponentPropsWithRef< C extends keyof JSX.IntrinsicElements | React.ComponentType, > = C extends AnyStyledComponent ? React.ComponentPropsWithRef> : React.ComponentPropsWithRef; export type StyledComponentInnerOtherProps = C extends StyledComponent< any, any, infer O, any > ? O : C extends StyledComponent ? O : never; export type StyledComponentInnerAttrs = C extends StyledComponent ? A : never; export interface ThemedBaseStyledInterface extends ThemedStyledComponentFactories { (component: C): ThemedStyledFunction< StyledComponentInnerComponent, T, StyledComponentInnerOtherProps, StyledComponentInnerAttrs >; >( // unfortunately using a conditional type to validate that it can receive a `theme?: Theme` // causes tests to fail in TS 3.1 component: C, ): ThemedStyledFunction; } export type ThemedStyledInterface = ThemedBaseStyledInterface>; export type StyledInterface = ThemedStyledInterface; export interface BaseThemedCssFunction { (first: TemplateStringsArray | CSSObject, ...interpolations: SimpleInterpolation[]): FlattenSimpleInterpolation; ( first: TemplateStringsArray | CSSObject | InterpolationFunction>, ...interpolations: Array>> ): FlattenInterpolation>;

( first: TemplateStringsArray | CSSObject | InterpolationFunction>, ...interpolations: Array>> ): FlattenInterpolation>; } export type ThemedCssFunction = BaseThemedCssFunction>; // Helper type operators // Pick that distributes over union types export type PickU = T extends any ? { [P in K]: T[P] } : never; export type OmitU = T extends any ? PickU> : never; type WithOptionalTheme

= OmitU & { theme?: T | undefined; }; type AnyIfEmpty = keyof T extends never ? any : T; export interface ThemedStyledComponentsModule { default: ThemedStyledInterface; css: ThemedCssFunction; // unfortunately keyframes can't interpolate props from the theme keyframes: (strings: TemplateStringsArray | CSSKeyframes, ...interpolations: SimpleInterpolation[]) => Keyframes; createGlobalStyle:

( first: TemplateStringsArray | CSSObject | InterpolationFunction>, ...interpolations: Array>> ) => GlobalStyleComponent; withTheme: BaseWithThemeFnInterface; ThemeProvider: BaseThemeProviderComponent; ThemeConsumer: React.Consumer; ThemeContext: React.Context; useTheme(): T; // This could be made to assert `target is StyledComponent` instead, but that feels not type safe isStyledComponent: typeof isStyledComponent; ServerStyleSheet: typeof ServerStyleSheet; StyleSheetManager: typeof StyleSheetManager; } declare const styled: StyledInterface; export const css: ThemedCssFunction; export type BaseWithThemeFnInterface = >( // this check is roundabout because the extends clause above would // not allow any component that accepts _more_ than theme as a prop component: React.ComponentProps extends { theme?: T | undefined } ? C : never, ) => React.ForwardRefExoticComponent< WithOptionalTheme>, T> >; export type WithThemeFnInterface = BaseWithThemeFnInterface>; export const withTheme: WithThemeFnInterface; export function useTheme(): DefaultTheme; /** * This interface can be augmented by users to add types to `styled-components`' default theme * without needing to reexport `ThemedStyledComponentsModule`. */ // Unfortunately, there is no way to write tests for this // as any augmentation will break the tests for the default case (not augmented). // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface DefaultTheme {} export interface ThemeProviderProps { children?: React.ReactNode | undefined; theme: T | ((theme: U) => T); } export type BaseThemeProviderComponent = React.ComponentClass< ThemeProviderProps >; export type ThemeProviderComponent = BaseThemeProviderComponent< AnyIfEmpty, AnyIfEmpty >; export const ThemeProvider: ThemeProviderComponent>; // NOTE: this technically starts as undefined, but allowing undefined is unhelpful when used correctly export const ThemeContext: React.Context>; export const ThemeConsumer: typeof ThemeContext["Consumer"]; export interface Keyframes { getName(): string; } export function keyframes( strings: TemplateStringsArray | CSSKeyframes, ...interpolations: SimpleInterpolation[] ): Keyframes; export function createGlobalStyle

( first: TemplateStringsArray | CSSObject | InterpolationFunction>, ...interpolations: Array>> ): GlobalStyleComponent; export function isStyledComponent(target: any): target is StyledComponent; export class ServerStyleSheet { collectStyles(tree: React.ReactNode): React.ReactElement<{ sheet: ServerStyleSheet }>; getStyleTags(): string; getStyleElement(): Array>; interleaveWithNodeStream(readableStream: NodeJS.ReadableStream): NodeJS.ReadableStream; readonly instance: this; seal(): void; clearTag(): void; } export type StylisPlugin = ( context: number, selector: string[], parent: string[], content: string, line: number, column: number, length: number, // eslint-disable-next-line @typescript-eslint/no-invalid-void-type ) => string | void; export interface StyleSheetManagerProps { children?: React.ReactNode; disableCSSOMInjection?: boolean | undefined; disableVendorPrefixes?: boolean | undefined; stylisPlugins?: StylisPlugin[] | undefined; sheet?: ServerStyleSheet | undefined; target?: HTMLElement | ShadowRoot | undefined; } export class StyleSheetManager extends React.Component {} /** * The CSS prop is not declared by default in the types as it would cause 'css' to be present * on the types of anything that uses styled-components indirectly, even if they do not use the * babel plugin. * * You can load a default declaration by using writing this special import from * a typescript file. This module does not exist in reality, which is why the {} is important: * * ```ts * import {} from 'styled-components/cssprop' * ``` * * Or you can declare your own module augmentation, which allows you to specify the type of Theme: * * ```ts * import { CSSProp } from 'styled-components' * * interface MyTheme {} * * declare module 'react' { * interface Attributes { * css?: CSSProp * } * } * ``` */ // ONLY string literals and inline invocations of css`` are supported, anything else crashes the plugin export type CSSProp> = string | CSSObject | FlattenInterpolation>; export default styled;