How to create your own Typescript library
October 12, 2019
Creating my own Typescript library is being my life for the last months, so I wanted share my experience and the steps you should follow to create your very own.
From my point of view, there are a lot of missing points on the Internet when you just want to start writing your code and get that library out. So, I'm going to provide you with a list of five steps you need to follow to create your Typescript library and make your users happy.
1. Setup.
First things first, creating a new project involves setting it up.
Create a new folder and initialize it.
$ mkdir library_name$ cd library_name$ npm init -y
This, will create a package.json
on your folder that look like this.
{"name": "library_name","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC"}
I expect you are familiar with those properties, but I'm going to explain you what are them for just in case:
name
is the name of the library.version
is the version the library is currelty at.description
is a short description of what the library does.main
is the file where users of your library are going to point at when they import it.scripts
is a list of tasks we will need to define (More on that later).keywors
is a list of words thatnpm
will use to link similar packages.author
should be you, so put your name on it.license
defines how users will be able to use your library for (comercial purposes...etc.)
2. Install dependencies.
There are three types of dependencies.
- dependencies, which are used for production code (code that you ship with your library).
- devDependencies, normally tools you use to make your developer experience better (nothing you ship with your library).
- peerDepedencies, dependant libraries (Let's say you are using react with hooks at your library. You might want to add a peer dependency on
react@>=16.8.0
which introduced hooks to make sure nobody uses your library with a version ofreact
which is less than16.8.0
).
Packages we need to install
typescript
, the compiler.rollup
my choice and recommendation of code bundler for libraries.rollup-plugin-typescript2
, this will make sure our code gets compiled to ES5.
Taking into account the concepts about types of dependencies above, where would you put these dependencies under?
In our example, typescript
and rollup
are tools that makes our development experience better, but you might be building a more complex library. In our case dependencies fall into devDependencies
.
$ npm i typescript rollup rollup-plugin-typescript2 --save-dev
3. Write yout library's code.
Enough of the boring, let's write some code.
We are ging to create a folder called src
in our root directory and a file called index.ts
(Note, this is my choice of folder structure, you can perfectly work with yours).
$ mkdir src$ cd src$ touch index.ts
This is going to be a really simple example, because I don't want to focus in the code too much, but to show you how to create your library.
Our library is going to export two functions, sum
and deduct
. Self explanatory names that will make the code easy to understand.
// index.tsexport function sum(a: number, b: number): number {return a + b}export function deduct(a: number, b: number): number {return a - b}
4. Configuration.
In this step we need to configure our project to make sure we export our code to our users in the right way.
Typescript
We need a tsconfig.json
file that will tell the compiler what are the rules that it needs to follow to compile our code.
{"compilerOptions": {"outDir": "lib","target": "es5","module": "esnext","lib": ["es2015"],"sourceMap": true,"strict": true,"strictFunctionTypes": true,"noImplicitReturns": true,"noImplicitThis": true,"noImplicitAny": true,"strictNullChecks": true,"alwaysStrict": true,"noUnusedLocals": true,"noUnusedParameters": true,"skipLibCheck": true,"declaration": true,"esModuleInterop": true},"include": ["src"],"exclude": ["node_modules", "lib", "**/*.test.ts"]}
Notice, target is
es5
in which our code will get compiled to, and we are usinges2015
, equivalent to ES6 to write our code.
Rollup
To configure rollup, we need a rollup.config.js
file in our root folder.
import typescript from 'rollup-plugin-typescript2'export default [{input: './src/index.ts',output: {file: './lib/index.esm.js',format: 'esm',},plugins: [typescript()],},{input: './src/index.ts',output: {file: './lib/index.js',format: 'cjs',},plugins: [typescript()],},]
We are going to export our code in two different formats, cjs
(short of commonjs) and also esm
(short of ESModules).
- CommonJS will allow our users to get all our code, just like any other library.
- ESModules will allow users to "tree shake" our code, meaning that if they only want to use
sum
from our library, they are not going to getdeduct
from it.
package.json
Now, that we have our code, we need to be able to compile and bundle it all together.
We are going to go back a bit on the post and remember the package.json
structure.
Remember we had scritps
which where tasks to run on our code? This is the perfect spot to execute commands to compile our code.
Add a build script.
{..."scripts": {"build": "rollup -c"},...}
And execute it.
$ npm run build
You should get something like this as output.
> library_name@1.0.0 build /Users/aganglada/dev/library_name> rollup -c./src/index.ts → ./lib/index.esm.js...created ./lib/index.esm.js in 529ms./src/index.ts → ./lib/index.js...created ./lib/index.js in 225ms
Now, check your folder structure, where lib
appeared with both esm
and cjs
files, together with index.d.ts
, which is our typescript declaration file.
Do you also remember the main
property? We said that this will be the entry to our code to our users when they import code from our library. In our case, we are going to add a new property called module
which will point to the esm
file.
{..."main": "lib/index.js","module": "lib/index.esm.js",...}
Another important thing is, we don't want our users to download our source code, instead we want them to get only our compiled code, so we need to add the files
property to our package.json
as well, where we will specify only the files that we want to publish.
{..."files": ["lib","package.json"]...}
5. And finally, publish
If you don't have an npm account, run
$ npm adduser
and this will automatically create an account on npmjs.com for you.
Otherwise, login with your account using the same command and run
$ npm publish
Your code will be ready to use in seconds!
Conclusion
At the end of this post, I hope you have learned how to create and publish your own library which works with Typescript and it's also "tree shackable" so users don't end up with all your code in their bundles.