├── docs
├── troubleshooting.md
├── next-steps
│ ├── README.md
│ ├── measure-type-coverage.md
│ ├── add-an-autoformatter.md
│ └── keep-your-dependencies-up-to-date.md
├── best-practices
│ ├── README.md
│ ├── optimize-the-production-build.md
│ ├── pick-a-unique-name.md
│ ├── do-not-suppress-compilation-errors.md
│ ├── make-incremental-builds-fast-for-easy-development.md
│ ├── do-not-depend-on-global-variables.md
│ └── make-your-public-api-augmentation-friendly.md
├── README.md
├── SUMMARY.md
├── frequently-asked-questions.md
└── configuration.md
├── .gitignore
├── .gitbook.yaml
├── .prettierrc
├── .vscode
└── extensions.json
├── README.md
├── LICENSE
└── .gitbook
└── assets
└── logo.svg
/docs/troubleshooting.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/next-steps/README.md:
--------------------------------------------------------------------------------
1 | # Next steps
2 |
3 |
--------------------------------------------------------------------------------
/docs/best-practices/README.md:
--------------------------------------------------------------------------------
1 | # Best practices
2 |
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .drafts/*
2 |
3 | .vscode/*
4 | !.vscode/extensions.json
5 |
--------------------------------------------------------------------------------
/.gitbook.yaml:
--------------------------------------------------------------------------------
1 | root: ./docs
2 |
3 | structure:
4 | readme: README.md
5 | summary: SUMMARY.md
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "proseWrap": "always",
4 | "tabWidth": 2,
5 | "useTabs": false
6 | }
7 |
--------------------------------------------------------------------------------
/docs/best-practices/optimize-the-production-build.md:
--------------------------------------------------------------------------------
1 | # Optimize the production build
2 |
3 | Probably the easiest way to build your project is to use [microbundle](https://github.com/developit/microbundle). It will optimize production builds for you as well as provide the `watch` mode for development.
4 |
5 |
--------------------------------------------------------------------------------
/docs/next-steps/measure-type-coverage.md:
--------------------------------------------------------------------------------
1 | # Measure type coverage
2 |
3 | Use [type-coverage](https://github.com/plantain-00/type-coverage) to make sure that type density in your codebase doesn't drop in the future. Set a goal \(for example 99%\) and run the tool against your codebase before you commit or push.
4 |
5 |
--------------------------------------------------------------------------------
/docs/best-practices/pick-a-unique-name.md:
--------------------------------------------------------------------------------
1 | # Pick a unique name
2 |
3 | Use the [Open Source Project Name Checker](http://ivantomic.com/projects/ospnc/) to check if no package uses it already. It may be a good idea to check for [available domains](https://zeit.co/domains) in case your project gets large and popular.
4 |
5 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "streetsidesoftware.code-spell-checker",
4 | "EditorConfig.EditorConfig",
5 | "bierner.markdown-checkbox",
6 | "bierner.markdown-preview-github-styles",
7 | "esbenp.prettier-vscode",
8 | "DavidAnson.vscode-markdownlint"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/docs/best-practices/do-not-suppress-compilation-errors.md:
--------------------------------------------------------------------------------
1 | # Do not suppress compilation errors
2 |
3 | Using `// @ts-ignore` comments in your source is a serious code smell. Not only does it hide ugliness, but it can also break your consumers' code when the `--removeComments` compiler flag is turned on, because stripping these comments will uncover compilation errors in your package.
4 |
5 |
--------------------------------------------------------------------------------
/docs/best-practices/make-incremental-builds-fast-for-easy-development.md:
--------------------------------------------------------------------------------
1 | # Make incremental builds fast for easy development
2 |
3 | If you are developing a Node.js library, use [ts-node-dev](https://github.com/whitecolor/ts-node-dev) for fast incremental rebuilds. It bundles [ts-node](https://github.com/TypeStrong/ts-node) together with [nodemon](https://github.com/remy/nodemon). It also watches your `tsconfig.json` for changes which makes prototyping easy and fast.
4 |
5 |
--------------------------------------------------------------------------------
/docs/next-steps/add-an-autoformatter.md:
--------------------------------------------------------------------------------
1 | # Add an autoformatter
2 |
3 | [Prettier](https://github.com/prettier/prettier) will take care of the formatting for you. Use [tslint-config-prettier](https://github.com/prettier/tslint-config-prettier) or [prettier-tslint](https://github.com/azz/prettier-tslint) to avoid conflicts between TSLint and Prettier.
4 |
5 | Optionally, run Prettier with a pre-commit/pre-push tool. [Learn more](https://prettier.io/docs/en/precommit.html).
6 |
7 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Getting started
2 |
3 | The objective of this guide is to collect everything you need to successfully publish a library created with TypeScript.
4 |
5 | This includes, but is not limited to:
6 |
7 | * [x] What are the recommended settings
8 | * [x] What are the common pitfalls
9 | * [x] Your pre-launch checklist
10 |
11 | ## Roadmap
12 |
13 | * [ ] Code examples
14 | * [ ] [Project references](https://www.typescriptlang.org/docs/handbook/project-references.html), Lerna and monorepos
15 | * [ ] Test runner configuration
16 | * [ ] Repository badges
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | # Create a TypeScript Library
8 |
9 | The objective of this guide is to collect everything you need to successfully publish a library
10 | created with TypeScript.
11 |
12 | This includes:
13 |
14 | - [x] What are the recommended settings
15 | - [x] What are the common pitfalls
16 | - [x] Your pre-launch checklist
17 |
18 | ## Documentation
19 |
20 | This guide is available at [library.typescript.guide](https://library.typescript.guide/).
21 |
22 | ## Roadmap
23 |
24 | - [ ] Code examples
25 | - [ ] [Project references](https://www.typescriptlang.org/docs/handbook/project-references.html),
26 | Lerna and monorepos
27 | - [ ] Test runner configuration
28 | - [ ] Repository badges
29 |
30 | ## Contributing
31 |
32 | Contributions of any kind are welcome. If you feel that something is missing, please open a pull
33 | request or [open an issue](https://github.com/karol-majewski/create-typescript-library/issues/new).
34 |
35 | ## License
36 |
37 | The MIT License.
38 |
--------------------------------------------------------------------------------
/docs/best-practices/do-not-depend-on-global-variables.md:
--------------------------------------------------------------------------------
1 | # Do not depend on global variables
2 |
3 | [Depend on an interface](https://en.wikipedia.org/wiki/Dependency_inversion_principle) instead.
4 |
5 | ## Example 1
6 |
7 | If your library is a wrapper for Web Storage, don't call `window.localStorage` directly.
8 |
9 | ### Bad
10 |
11 | When `localStorage` is unavailable \(think Safari Private Mode on iOS\), this function will throw an exception.
12 |
13 | ```typescript
14 | function get(key: string): string | null {
15 | localStorage.get(key);
16 | }
17 | ```
18 |
19 | ### Good
20 |
21 | Your consumers must bring their own `Storage` — be it `localStorage`, `sessionStorage` or a custom `Storage`.
22 |
23 | ```typescript
24 | function get(key: string, storage: Storage): string | null {
25 | storage.get(key);
26 | }
27 | ```
28 |
29 | ### Good
30 |
31 | Your consumers _can_ bring their own `Storage` if they want, and `localStorage` is used by default.
32 |
33 | ```typescript
34 | function get(key: string, storage: Storage = localStorage): string | null {
35 | storage.get(key);
36 | }
37 | ```
38 |
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Karol Majewski
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitbook/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Table of contents
2 |
3 | * [Getting started](README.md)
4 | * [Configuration](configuration.md)
5 | * [Best practices](best-practices/README.md)
6 | * [Pick a unique name](best-practices/pick-a-unique-name.md)
7 | * [Optimize the production build](best-practices/optimize-the-production-build.md)
8 | * [Make incremental builds fast for easy development](best-practices/make-incremental-builds-fast-for-easy-development.md)
9 | * [Make your public API augmentation-friendly](best-practices/make-your-public-api-augmentation-friendly.md)
10 | * [Do not depend on global variables](best-practices/do-not-depend-on-global-variables.md)
11 | * [Do not suppress compilation errors](best-practices/do-not-suppress-compilation-errors.md)
12 | * [Next steps](next-steps/README.md)
13 | * [Add an autoformatter](next-steps/add-an-autoformatter.md)
14 | * [Measure type coverage](next-steps/measure-type-coverage.md)
15 | * [Keep your dependencies up to date](next-steps/keep-your-dependencies-up-to-date.md)
16 | * [FAQ](frequently-asked-questions.md)
17 |
18 | ## See also
19 |
20 | * [Starting an Open Source Project](https://opensource.guide/starting-a-project/)
21 | * [How to promote your GitHub project](https://hackernoon.com/how-to-promote-your-github-project-1b39a7eee841)
22 |
23 |
--------------------------------------------------------------------------------
/docs/frequently-asked-questions.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | ## Should I transpile my code to ES5 in 2019?
4 |
5 | Excellent question! The best way out of this problem is to simultaneously ship two versions of your project: a CommonJS module \(legacy\) and a modern ECMAScript one. That's what [microbundle](https://github.com/developit/microbundle) can do for you out of the box.
6 |
7 | Read more: [Deploying ES2015+ Code in Production Today](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/).
8 |
9 | ## My library is a React component. Is there anything I need to know?
10 |
11 | React components are just JavaScript functions \(or classes\), so there isn't anything special about them. However, if your component is a [Higher-Order Component](https://reactjs.org/docs/higher-order-components.html), you can make the developer experience better by doing the following:
12 |
13 | * Export the interface describing the props supplied by your HOC
14 | * Export the interface telling your user what props must be supplied
15 | * If your HOC accepts a React component and returns a React component, the props accepted by the
16 |
17 | created component should not include the props already supplied by your HOC
18 |
19 | * Expose the wrapped component by using a static property or
20 |
21 | [`forwardRef`](https://reactjs.org/docs/forwarding-refs.html)
22 |
23 | ## I don't want to rewrite my library. I just want to add type definitions to it.
24 |
25 | It's best to submit your type definitions to [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped).
26 |
27 |
--------------------------------------------------------------------------------
/docs/next-steps/keep-your-dependencies-up-to-date.md:
--------------------------------------------------------------------------------
1 | # Keep your dependencies up to date
2 |
3 | JavaScript ecosystem is know for its frequent updates. It's even more true for TypeScript, because when the source code of your dependency and its type definitions live in two different places \(DefinitelyTyped\), you can expect them to evolve asynchronously. It's important to make sure _your_ dependencies are well-defined and deterministic in their behavior.
4 |
5 | ## Saving exact versions
6 |
7 | One solution to this problem is to save [exact versions](https://docs.npmjs.com/cli/install) of your dependencies.
8 |
9 | ```bash
10 | npm install --save-exact
11 | ```
12 |
13 | This will opt-out of the default `npm install` behavior which takes semantic versioning into account. While it makes your builds deterministic, it has a severe disadvantage: it makes it more difficult to reuse already installed packages, since they will rarely match the same version.
14 |
15 | ## Automatic updates
16 |
17 | A better solution is to have a tool like [Greenkeeper](https://greenkeeper.io/) or [Dependabot](https://dependabot.com/) scan the npm registry for updates and open a pull request when they are found. When a dependency from within the desired version range is going to break your build, a pull request with the details will be created for you.
18 |
19 | ## Manual updates
20 |
21 | Greenkeeper and Dependabot are free for open source projects. If your project is private and you are ale looking for a free solution, you can create an npm script running `npx npm-check`.
22 |
23 | In your `package.json`, add a script like this one:
24 |
25 | ```javascript
26 | {
27 | "scripts": {
28 | "dependencies:update": "npx npm-check --update"
29 | }
30 | }
31 | ```
32 |
33 | Running `npm run dependencies:update` will open an interactive panel in your terminal. Cherry-pick the packages you are interested in and hit Enter to confirm.
34 |
35 |
--------------------------------------------------------------------------------
/docs/best-practices/make-your-public-api-augmentation-friendly.md:
--------------------------------------------------------------------------------
1 | # Make your public API augmentation-friendly
2 |
3 | Once a package is published, its type definitions are often [augmented](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) by the consumers. There are a few reasons for that:
4 |
5 | * **Type definitions are not precise enough.** If a public API makes use of broad types \(like `any` or `{}`\), not only does it defeat the purpose of using TypeScript — but it may also conflict with TSLint rules like [`no-unsafe-any`](https://palantir.github.io/tslint/rules/no-unsafe-any/), forcing the consumer to use a type assertion.
6 | * **A new version of TypeScript was released in the meantime.** TypeScript has a relatively short release cycle. When a new feature lands, it can used to get more type safety out of your code.
7 | * **Functionality was added to your library, but its type definitions do not reflect that.** That's often the case when the source code is at least partially created with JavaScript.
8 |
9 | By allowing your consumers to augment the type definitions bundled with your package, you can create a safe environment in which everyone can get what they want without being dependent on each other.
10 |
11 | What does it mean for a pubic interface to be augmentation friendly?
12 |
13 | * Functions and methods are described with interfaces \(_call signatures_\), not function types. This
14 |
15 | makes it possible to add overload definitions for them.
16 |
17 | * Type definitions are built of small definitions composed together. It makes it easier to import
18 |
19 | just a small subset of a type definition and reuse it \(instead of having to decompose a big
20 |
21 | definition yourself\).
22 |
23 | * If it depends on third party types, ECMAScript import syntax is used instead of
24 |
25 | [triple-slash directives](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html).
26 |
27 |
--------------------------------------------------------------------------------
/docs/configuration.md:
--------------------------------------------------------------------------------
1 | # Configuration
2 |
3 | ## Repository contents
4 |
5 | * [ ] Your package has a README. Read more at [makeareadme.com](https://www.makeareadme.com/).
6 | * [ ] Your package has a license. Not sure which should you choose? Go to [choosealicense.com](https://choosealicense.com/).
7 |
8 | ## `package.json`
9 |
10 | Generate the file by running `npm init` or `yarn init`. Once it's done, make sure:
11 |
12 | * [ ] The required fields are present \(`name`, `main`, `version`\)
13 | * [ ] The `main` field points to an existing file
14 | * [ ] The `types` \(or `typings`\) field points to a type declaration \(`*.d.ts`\) file
15 | * [ ] The `typesVersions` field, if used, follows the
16 |
17 | [correct syntax](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html)
18 |
19 | * [ ] The `files` field includes your JavaScript artifacts as well as your declaration files
20 | * [ ] A corresponding lockfile \(either `package-lock.json` or `yarn.lock`\) is generated and committed to the repository
21 |
22 | Read more about `package.json` in the [official documentation](https://docs.npmjs.com/files/package.json) and [here](https://github.com/stereobooster/package.json).
23 |
24 | ## `tsconfig.json`
25 |
26 | It's best to create your `tsconfig.json` by running `tsc --init` in your terminal. A configuration file generated this way makes the decisions explicit, and it also provides comments useful for any collaborators not familiar with TypeScript.
27 |
28 | Once that's done, make sure that:
29 |
30 | * [ ] `sourceMap` is set to `true`
31 | * [ ] `declaration` is set to `true`
32 | * [ ] `declarationMap` is set to `true`
33 | * [ ] `removeComments` is set to `false`
34 | * [ ] `strict` is set to `true`
35 | * [ ] `allowSyntheticDefaultImports` is set to `true`
36 | * [ ] `moduleResolution` is set to `"node"`
37 | * [ ] `esModuleInterop` is set to `true`
38 |
39 | Read more about [the options available in `tsconfig.json`.](https://www.typescriptlang.org/docs/handbook/compiler-options.html)
40 |
41 |
--------------------------------------------------------------------------------