From fb54c9361dfe8e9556a0de924cf9e0926800a70e Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Thu, 18 Oct 2018 00:33:35 +0200 Subject: [PATCH] feat: add typescript definitions fixes #197 --- .circleci/config.yml | 5 ++-- .gitignore | 3 -- package.json | 7 ++++- src/react/styled.js | 7 +++-- tsconfig.json | 13 +++++++++ typings/__fixtures__/index.tsx | 28 +++++++++++++++++++ typings/__fixtures__/react.tsx | 44 +++++++++++++++++++++++++++++ typings/__fixtures__/server.tsx | 9 ++++++ typings/index.d.ts | 49 +++++++++++++++++++++++++++++++++ yarn.lock | 23 ++++++++++++++++ 10 files changed, 179 insertions(+), 9 deletions(-) create mode 100644 tsconfig.json create mode 100644 typings/__fixtures__/index.tsx create mode 100644 typings/__fixtures__/react.tsx create mode 100644 typings/__fixtures__/server.tsx create mode 100644 typings/index.d.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index 8df782152..617db9c2e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,7 +30,7 @@ jobs: - persist_to_workspace: root: . paths: . - lint-and-flow: + lint-and-typecheck: <<: *defaults steps: - attach_workspace: @@ -38,6 +38,7 @@ jobs: - run: | yarn lint yarn flow + yarn typescript unit-tests: <<: *defaults steps: @@ -74,7 +75,7 @@ workflows: build-and-test: jobs: - install-dependencies - - lint-and-flow: + - lint-and-typecheck: requires: - install-dependencies - unit-tests: diff --git a/.gitignore b/.gitignore index dd26ab471..59878bc80 100644 --- a/.gitignore +++ b/.gitignore @@ -41,9 +41,6 @@ build/Release node_modules/ jspm_packages/ -# Typescript v1 declaration files -typings/ - # Optional npm cache directory .npm diff --git a/package.json b/package.json index 407b2c31c..c917c3043 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,10 @@ "version": "1.0.0-alpha.13", "description": "Blazing fast zero-runtime CSS in JS library", "main": "lib/index.js", + "types": "typings/index.d.ts", "files": [ "lib/", + "typings/", "react.js", "server.js", "babel.js", @@ -29,6 +31,7 @@ "scripts": { "lint": "eslint .", "flow": "flow", + "typescript": "tsc", "test": "jest", "test:unit": "jest __tests__", "test:integration": "jest __integration-tests__", @@ -50,6 +53,7 @@ "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", "@callstack/eslint-config": "^2.0.0", + "@types/react": "^16.4.18", "all-contributors-cli": "^5.4.0", "babel-core": "^7.0.0-bridge.0", "codecov": "^3.1.0", @@ -65,7 +69,8 @@ "puppeteer": "^1.8.0", "react": "^16.5.1", "react-test-renderer": "^16.5.2", - "release-it": "^7.6.1" + "release-it": "^7.6.1", + "typescript": "^3.1.3" }, "dependencies": { "@babel/core": "^7.0.1", diff --git a/src/react/styled.js b/src/react/styled.js index cbf5c0c40..cff4f49d3 100644 --- a/src/react/styled.js +++ b/src/react/styled.js @@ -78,12 +78,13 @@ if (process.env.NODE_ENV !== 'production') { } /* :: -type StyledComponent = React.ComponentType; +type StyledComponent = React.ComponentType<{ ...T, as?: React$ElementType, className?: string }>; type StyledTag = (strings: string[], ...exprs: Array string | number)>) => StyledComponent; -declare module.exports: {| +type StyledJSXIntrinsics = $ObjMap<$JSXIntrinsics, ({ props: T }) => StyledTag>; + +declare module.exports: StyledJSXIntrinsics & {| (T): StyledTag>, - [string]: StyledTag<{ children?: React.Node, [key: string]: any }>, |}; */ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..698de8c1e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6", "dom"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react" + } +} diff --git a/typings/__fixtures__/index.tsx b/typings/__fixtures__/index.tsx new file mode 100644 index 000000000..8b7d5c3f8 --- /dev/null +++ b/typings/__fixtures__/index.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { css, cx } from 'linaria'; + +const tomato = 'tomato'; +const border = 1; + +const absoluteFill = { + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, +}; + +const title = css` + color: ${tomato}; + border-width: ${border}px; + + &.abs { + ${absoluteFill}; + } +`; + +const heading = css` + font-family: sans-serif; +`; + +

Hello world

; diff --git a/typings/__fixtures__/react.tsx b/typings/__fixtures__/react.tsx new file mode 100644 index 000000000..ccf429d1a --- /dev/null +++ b/typings/__fixtures__/react.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { styled } from 'linaria/react'; + +const white = 'white'; +const tomato = 'tomato'; +const border = 1; + +const absoluteFill = { + position: 'absolute', + top: 0, + left: 0, + bottom: 0, + right: 0, +}; + +const Button = styled.button` + color: ${white}; + background-color: ${props => props.background}; + border-width: ${border}px; + + &.abs { + ${absoluteFill}; + } +`; + +const CustomButton = styled(Button)` + &:hover { + background-color: ${tomato}; + } +`; + +class Title extends React.Component<{ label: string; className: string }> { + render() { + return

{this.props.label}

; + } +} + +const CustomTitle = styled(Title)` + font-family: sans-serif; +`; + +; + alert('Clicked')}>Hello world; +; diff --git a/typings/__fixtures__/server.tsx b/typings/__fixtures__/server.tsx new file mode 100644 index 000000000..5e8a7f0c2 --- /dev/null +++ b/typings/__fixtures__/server.tsx @@ -0,0 +1,9 @@ +import { collect } from 'linaria/server'; + +const { critical, other } = collect( + '
Hello
', + '.foo { color: blue; }' +); + +critical.toLowerCase(); +other.toLowerCase(); diff --git a/typings/index.d.ts b/typings/index.d.ts new file mode 100644 index 000000000..5e39fbacf --- /dev/null +++ b/typings/index.d.ts @@ -0,0 +1,49 @@ +declare module 'linaria' { + export const css: ( + strings: TemplateStringsArray, + ...exprs: Array + ) => string; + + export const cx: ( + ...classNames: Array + ) => string; +} + +declare module 'linaria/react' { + import * as React from 'react'; + + type Overwrite = { [P in Exclude]: T1[P] } & T2; + + type InterpolationFunction = (props: T) => string | number; + + type StyledComponent = React.ComponentType< + Overwrite; className?: string }> + >; + + type StyledTag = ( + strings: TemplateStringsArray, + ...exprs: Array> + ) => StyledComponent; + + type StyledJSXIntrinsics = { + [P in keyof JSX.IntrinsicElements]: StyledTag< + JSX.IntrinsicElements[P] & { [key: string]: any } + > + }; + + export const styled: StyledJSXIntrinsics & { + (component: React.ReactType): StyledTag; + + [key: string]: StyledTag<{ + children?: React.ReactNode; + [key: string]: any; + }>; + }; +} + +declare module 'linaria/server' { + export const collect: ( + html: string, + css: string + ) => { critical: string; other: string }; +} diff --git a/yarn.lock b/yarn.lock index 851f7f6fa..620a72e9b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1000,6 +1000,19 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== +"@types/prop-types@*": + version "15.5.6" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.6.tgz#9c03d3fed70a8d517c191b7734da2879b50ca26c" + integrity sha512-ZBFR7TROLVzCkswA3Fmqq+IIJt62/T7aY/Dmz+QkU7CaW2QFqAitCE8Ups7IzmGhcN1YWMBT4Qcoc07jU9hOJQ== + +"@types/react@^16.4.18": + version "16.4.18" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.18.tgz#2e28a2e7f92d3fa7d6a65f2b73275c3e3138a13d" + integrity sha512-eFzJKEg6pdeaukVLVZ8Xb79CTl/ysX+ExmOfAAqcFlCCK5TgFDD9kWR0S18sglQ3EmM8U+80enjUqbfnUyqpdA== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + JSONStream@^1.0.4: version "1.3.4" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.4.tgz#615bb2adb0cd34c8f4c447b5f6512fa1d8f16a2e" @@ -2727,6 +2740,11 @@ cssstyle@^1.0.0: dependencies: cssom "0.3.x" +csstype@^2.2.0: + version "2.5.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.7.tgz#bf9235d5872141eccfb2d16d82993c6b149179ff" + integrity sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw== + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -7899,6 +7917,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.3.tgz#01b70247a6d3c2467f70c45795ef5ea18ce191d5" + integrity sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA== + uglify-js@^2.6: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"