DimiMikadze / create-react-library

React NPM library starter kit based on Facebook's create react app
MIT License
602 stars 60 forks source link

TypeScript support #54

Closed karianpour closed 5 years ago

karianpour commented 5 years ago

As create-react-app supports TypeScript, do you have any plan to support it as well?

DimiMikadze commented 5 years ago

@karianpour Hi, yes we can add instructions in readme how to use TypeScript, can you send the PR for it? If not i'll do it, in the next week 👍

WilliamChou06 commented 5 years ago

@karianpour You can add TypeScript by following the standard CRA way to do it plus a little tweaking:

1. Install CRA TypeScript packages:

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

2. Create a tsconfig.json file in the root folder. This is mine based on the default CRA one:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "noImplicitAny": false,
    "strictNullChecks": false,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "noImplicitThis": true
  },
  "include": [
    "src"
  ]
}

3. And edit .js extensions to .ts and .tsx in 'config/paths.js' as needed:

// config after eject: we're in ./config/
module.exports = {
  dotenv: resolveApp('.env'),
  appPath: resolveApp('.'),
  appBuild: resolveApp('build'),
  appDemoBuild: resolveApp('demo'), // CRL: Added for demo purposes
  appPublic: resolveApp('public'),
  appHtml: resolveApp('public/index.html'),
  appIndexJs: resolveApp('src/demo/index.tsx'), // CRL: Updated for demo purposes
  appPackageJson: resolveApp('package.json'),
  appSrc: resolveApp('src'),
  appTsConfig: resolveApp('tsconfig.json'),
  appJsConfig: resolveApp('jsconfig.json'),
  yarnLockFile: resolveApp('yarn.lock'),
  testsSetup: resolveApp('src/setupTests.ts'),
  proxySetup: resolveApp('src/setupProxy.js'),
  appNodeModules: resolveApp('node_modules'),
  publicUrl: getPublicUrl(resolveApp('package.json')),
  servedPath: getServedPath(resolveApp('package.json')),

  // CRL: New paths for demo build
  appDemoIndexJs: resolveApp('src/demo/index.tsx'),
  appDemoSrc: resolveApp('src/demo'),

  // CRL: New paths for library
  appLibIndexJs: resolveApp('src/lib/index.ts'),
  appLibSrc: resolveApp('src/lib'),
};

And that should be it!

Cheers! 😄

karianpour commented 5 years ago

@WilliamChou06, Actually I am keen to not eject from CRA. @DimiMikadze, I could do it with CRA, and changing package.json, tsconfig.json for building I used the following command :

"scripts": {
    "build": "rm -rf dist && tsc --build ./tsconfig.build.json && copyfiles -u 2 ./src/lib/**/*.html ./src/lib/**/*.css ./dist/",
}

tsconfig.build.json :

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "jsx": "react",
    "declaration": true,
    "outDir": "dist"
  },
  "include": [
    "src/lib/**/*",
    "src/lib/**/**/*"
  ]
}

I have a lib directory for the library files, and example directory for showing usage and demo. This way is not robust, I would say, but works for my limited use case, here is the repo in case some-one needed to checkout.