diff --git a/packages/emotion-theming/package.json b/packages/emotion-theming/package.json index bd1fe3f7fd..530e1044a0 100644 --- a/packages/emotion-theming/package.json +++ b/packages/emotion-theming/package.json @@ -4,12 +4,15 @@ "description": "A CSS-in-JS theming solution, inspired by styled-components", "main": "dist/index.cjs.js", "module": "dist/index.es.js", + "types": "typings/emotion-theming.d.ts", "files": [ "src", "dist" ], "scripts": { "build": "npm-run-all clean rollup rollup:umd", + "test:typescript": "tsc --noEmit -p typescript_tests/tsconfig.json", + "pretest:typescript": "npm run build", "clean": "rimraf dist", "rollup": "rollup -c ../../rollup.config.js", "watch": "rollup -c ../../rollup.config.js --watch", @@ -34,10 +37,12 @@ }, "homepage": "https://github.com/emotion-js/emotion#readme", "devDependencies": { + "@types/react": "^16.0.14", "cross-env": "^5.0.1", "prop-types": "^15.5.8", "rimraf": "^2.6.1", - "rollup": "^0.43.0" + "rollup": "^0.43.0", + "typescript": "^2.5.3" }, "dependencies": { "hoist-non-react-statics": "^2.3.1" diff --git a/packages/emotion-theming/typescript_tests/tsconfig.json b/packages/emotion-theming/typescript_tests/tsconfig.json new file mode 100644 index 0000000000..ecd8ba628d --- /dev/null +++ b/packages/emotion-theming/typescript_tests/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "declaration": true, + "strict": true, + "allowSyntheticDefaultImports": true, + "moduleResolution": "node", + "jsx": "react" + }, + "include": [ + "./*.ts", + "./*.tsx" + ] +} diff --git a/packages/emotion-theming/typescript_tests/typescript_tests.tsx b/packages/emotion-theming/typescript_tests/typescript_tests.tsx new file mode 100644 index 0000000000..878ad916a8 --- /dev/null +++ b/packages/emotion-theming/typescript_tests/typescript_tests.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import * as emotionTheming from '../'; +import { ThemeProvider, withTheme, EmotionThemingModule } from '../'; + +const theme = { primary: "green", secondary: "white" }; +const CompSFC = (props: { prop: boolean }) =>
; +declare class CompC extends React.Component<{ prop: boolean }> { } + +/** + * Theme Provider with no type + */ +; + theme} />; + +/** + * withTheme with no type + */ +const ThemedSFC = withTheme(CompSFC); +; +; + +const ThemedComp = withTheme(CompC); +; + + +const { ThemeProvider: TypedThemeProvider, withTheme: typedWithTheme } = emotionTheming as EmotionThemingModule; + +; +; + ({ primary: theme.primary, secondary: theme.secondary })} />; + +const TypedThemedSFC = typedWithTheme(ThemedSFC); +; + + +const TypedCompSFC = typedWithTheme(CompSFC); +; +; \ No newline at end of file diff --git a/packages/emotion-theming/typings/emotion-theming.d.ts b/packages/emotion-theming/typings/emotion-theming.d.ts new file mode 100644 index 0000000000..ea931cf561 --- /dev/null +++ b/packages/emotion-theming/typings/emotion-theming.d.ts @@ -0,0 +1,20 @@ +import { ComponentClass, SFC } from "react"; + +export type OptionalThemeProps = Props & { theme?: Theme }; + +export interface ThemeProviderProps { + theme: Partial | { (theme: Theme): Theme }; +} + +export type ThemeProviderComponent = ComponentClass>; +export const ThemeProvider: ThemeProviderComponent; + +/** + * Inject theme into component + */ +export function withTheme(component: ComponentClass | SFC): ComponentClass>; + +export interface EmotionThemingModule { + ThemeProvider: ThemeProviderComponent; + withTheme(component: ComponentClass | SFC): ComponentClass>; +} \ No newline at end of file diff --git a/packages/react-emotion/typescript_tests/typescript_tests.tsx b/packages/react-emotion/typescript_tests/typescript_tests.tsx index f0902fceee..16d1cd4edb 100644 --- a/packages/react-emotion/typescript_tests/typescript_tests.tsx +++ b/packages/react-emotion/typescript_tests/typescript_tests.tsx @@ -66,6 +66,8 @@ const SFCComponent: React.StatelessComponent = props => (
{props.children} {props.foo}
); +declare class MyClassC extends React.Component { }; + // infer SFCComponentProps Component = styled(SFCComponent)({ color: 'red' }); mount = ; @@ -74,6 +76,9 @@ mount = ; Component = styled(SFCComponent)`color: red`; mount = ; +Component = styled(MyClassC) ``; +mount = ; + // do not infer SFCComponentProps with pass CustomProps, need to pass both Component = styled(SFCComponent)({ color: 'red', diff --git a/packages/react-emotion/typings/react-emotion.d.ts b/packages/react-emotion/typings/react-emotion.d.ts index 3f2b97bbe1..902da2bd4a 100644 --- a/packages/react-emotion/typings/react-emotion.d.ts +++ b/packages/react-emotion/typings/react-emotion.d.ts @@ -1,4 +1,4 @@ -import { StatelessComponent, Component as ClassComponent, CSSProperties } from 'react' +import { StatelessComponent, ComponentClass, CSSProperties } from 'react' import { Interpolation as EmotionInterpolation } from 'emotion' export * from 'emotion' @@ -27,7 +27,7 @@ export interface Options { } type Component = - | ClassComponent + | ComponentClass | StatelessComponent export type ThemedProps = Props & { @@ -36,7 +36,7 @@ export type ThemedProps = Props & { export interface StyledComponent extends - ClassComponent, + ComponentClass, StatelessComponent { withComponent(tag: Tag): @@ -95,7 +95,7 @@ type ShorthandsFactories = { export interface ThemedReactEmotionInterface extends ShorthandsFactories { // overload for dom tag ( - tag: Tag | Component, + tag: Tag, options?: Options, ): CreateStyled