// Type definitions for styled-components 5.1 // Project: https://github.com/styled-components/styled-components, https://styled-components.com // Definitions by: Igor Oleinikov // Ihor Chulinda // Adam Lavin // Jessica Franco // Jason Killian // Sebastian Silbermann // David Ruisinger // Matthew Wagerfield // Yuki Ito // Maciej Goszczycki // Danilo Fuchs // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // forward declarations declare global { namespace NodeJS { // tslint:disable-next-line:no-empty-interface interface ReadableStream {} } } import * as CSS from 'csstype'; import * as React from 'react'; import * as hoistNonReactStatics from 'hoist-non-react-statics'; 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 : Pick> & Partial>> & Partial>> : never; type ReactDefaultizedProps = C extends { defaultProps: infer D } ? Defaultize : P; type MakeAttrsOptional, O extends object, A extends keyof any> = Omit< ReactDefaultizedProps< C, React.ComponentPropsWithRef ? C : never> > & O, A > & Partial< Pick ? C : never> & O, A> >; 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 "as" prop AsC extends string | React.ComponentType = C, // 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 & MakeAttrsOptional, T > & WithChildrenIfReactComponentClass : never; // Because of React typing quirks, when getting props from a React.ComponentClass, // we need to manually add a `children` field. // See https://github.com/DefinitelyTyped/DefinitelyTyped/pull/31945 // and https://github.com/DefinitelyTyped/DefinitelyTyped/pull/32843 type WithChildrenIfReactComponentClass> = C extends React.ComponentClass< any > ? { children?: React.ReactNode } : {}; 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; forwardedAs?: FAsC }; 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 = ReadonlyArray; export type InterpolationFunction

= (props: P) => Interpolation

; type Attrs, T> = ((props: ThemedStyledProps) => A) | A; export type ThemedGlobalStyledClassProps = WithOptionalTheme & { suppressMultiMountWarning?: boolean; }; export interface GlobalStyleComponent extends React.ComponentClass> {} // remove the call signature from StyledComponent so Interpolation can still infer InterpolationFunction type StyledComponentInterpolation = | Pick, keyof StyledComponentBase> | Pick, keyof StyledComponentBase>; // abuse Pick to strip the call signature from ForwardRefExoticComponent type ForwardRefExoticBase

= Pick, keyof React.ForwardRefExoticComponent>; // Config to be used with withConfig export interface StyledConfig { // TODO: Add all types from the original StyledComponentWrapperProperties shouldForwardProp?: (prop: keyof O, defaultValidatorFn: (prop: keyof O) => boolean) => boolean; } // 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; forwardedAs?: never }): React.ReactElement< StyledComponentProps >; = C, FAsC extends string | React.ComponentType = C>( 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 type Omit = Pick>; type WithOptionalTheme

= Omit & { theme?: T; }; 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: WithThemeFnInterface; ThemeProvider: ThemeProviderComponent; 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 } ? C : never, ) => React.ForwardRefExoticComponent, 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). // tslint:disable-next-line:no-empty-interface export interface DefaultTheme {} export interface ThemeProviderProps { children?: React.ReactNode; 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; } export type StylisPlugin = ( context: number, selector: string[], parent: string[], content: string, line: number, column: number, length: number, ) => string | void; export interface StyleSheetManagerProps { disableCSSOMInjection?: boolean; disableVendorPrefixes?: boolean; stylisPlugins?: StylisPlugin[]; sheet?: ServerStyleSheet; target?: HTMLElement; } 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;