DEV Community

Cover image for How to create and publish a TypeScript package.
Anish Prashun
Anish Prashun

Posted on • Updated on

How to create and publish a TypeScript package.

Introduction

In this guide, we will build a package for generating currency symbols from their respective
currency code using typescript and publish it as a Node.js package.

This is what we are going to build:
Currency-symbols-generator NPM
Github Repo

Alright.Let's get started!

Make sure you have the latest version of node and npm.

node -v
v16.13.2

npm -v
8.1.2
Enter fullscreen mode Exit fullscreen mode

Pick a great name

This is probably harder than you think. The package name must be Pascal Case and lowercase. With over 1,800,000 packages, do a quick search at https://www.npmjs.com/ to make sure your name isn't used yet. In this guide, we'll choose the name currency-symbol-generator, but make sure to use a unique name so you can publish the package, later on, npm 🚀.

Open you workspace where you want to create your package

In this we will be using our Desktop directory

cd Desktop
Enter fullscreen mode Exit fullscreen mode

Let's initialise our Package

We will be using TSDX in this guide as it provides all the necessary dependencies. You can change the name currency-symbol-generator to your own package name, as it will generate a package.json with the same name.

npx tsdx create currency-symbol-generator
Enter fullscreen mode Exit fullscreen mode

choose basic option when asked in the terminal and press enter.

Then change your directory to the package folder.

cd currency-symbol-generator
Enter fullscreen mode Exit fullscreen mode

Note - Be sure to use the name as specified while creating the package using tsdx.

Create a git repository

All in order. You need a remote git repository for the package so you can download it. Creating a remote Git repository isn't relevant to this article, but once you've created it, you can use the following lines to initialise your local repository and set up a remote origin.

git init
echo "# Currency Symbol Generator" >> README.md
git add . && git commit -m "Initial commit"
git branch -M main
Enter fullscreen mode Exit fullscreen mode

Replace with the URL to your remote repository.

git remote add origin <Git Repository Url>
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Modify your package.json

Add author, description, keywords, repository and bugs key in package.json.

Your package.json should look like this.

{
  "author": "Anish Prashun <anishprashun118@gmail.com",
  "version": "0.1.0",
  "license": "MIT",
  "description": "A minimal package for getting symbol of a currency using the country code.",
  "keywords": [
    "currency",
    "symbol",
    "react",
    "typescript",
    "javascript",
    "currency symbol",
    "get currency symbol",
    "anish prashun"
  ],
  "main": "dist/index.js",
  "typings": "dist/index.d.ts",
  "files": [
    "dist",
    "src"
  ],
  "repository": {
    "type": "git",
    "url": "https://github.com/Anishpras/currency-symbol-generator",
    "directory": "/"
  },
  "bugs": {
    "url": "https://github.com/Anishpras/currency-symbol-generator/issues"
  },
  "engines": {
    "node": ">=10"
  },
  "scripts": {
    "start": "tsdx watch",
    "build": "tsdx build",
    "test": "tsdx test",
    "lint": "tsdx lint",
    "prepare": "tsdx build",
    "size": "size-limit",
    "analyze": "size-limit --why"
  },
  "peerDependencies": {},
  "husky": {
    "hooks": {
      "pre-commit": "tsdx lint"
    }
  },
  "prettier": {
    "printWidth": 80,
    "semi": true,
    "singleQuote": true,
    "trailingComma": "es5"
  },
  "name": "currency-symbol-generator",
  "module": "dist/currency-symbol-generator.esm.js",
  "size-limit": [
    {
      "path": "dist/currency-symbol-generator.cjs.production.min.js",
      "limit": "10 KB"
    },
    {
      "path": "dist/currency-symbol-generator.esm.js",
      "limit": "10 KB"
    }
  ],
  "devDependencies": {
    "@size-limit/preset-small-lib": "^7.0.5",
    "husky": "^7.0.4",
    "size-limit": "^7.0.5",
    "tsdx": "^0.14.1",
    "tslib": "^2.3.1",
    "typescript": "^4.5.4"
  }
}
Enter fullscreen mode Exit fullscreen mode

Note - Change the details according to your need, like change the author name to your name and respectively.

Let's get to the real code now.

Create a currencyList.ts under src folder and create a array that contains all the symbols respective to their currency code.

const currencyList = [
  { name: 'AED', symbol: 'د.إ' },
  { name: 'AFN', symbol: '؋' },
  { name: 'ALL', symbol: 'L' },
  { name: 'AMD', symbol: '֏' },
  { name: 'ANG', symbol: 'ƒ' },
  { name: 'AOA', symbol: 'Kz' },
  { name: 'ARS', symbol: '$' },
  { name: 'AUD', symbol: '$' },
  { name: 'AWG', symbol: 'ƒ' },
  { name: 'AZN', symbol: '₼' },
  { name: 'BAM', symbol: 'KM' },
  { name: 'BBD', symbol: '$' },
  { name: 'BDT', symbol: '৳' },
  { name: 'BGN', symbol: 'лв' },
  { name: 'BHD', symbol: '.د.ب' },
  { name: 'BIF', symbol: 'FBu' },
  { name: 'BMD', symbol: '$' },
  { name: 'BND', symbol: '$' },
  { name: 'BOB', symbol: '$b' },
  { name: 'BRL', symbol: 'R$' },
  { name: 'BSD', symbol: '$' },
  { name: 'BTC', symbol: '฿' },
  { name: 'BTN', symbol: 'Nu.' },
  { name: 'BWP', symbol: 'P' },
  { name: 'BYR', symbol: 'Br' },
  { name: 'BYN', symbol: 'Br' },
  { name: 'BZD', symbol: 'BZ$' },
  { name: 'CAD', symbol: '$' },
  { name: 'CDF', symbol: 'FC' },
  { name: 'CHF', symbol: 'CHF' },
  { name: 'CLP', symbol: '$' },
  { name: 'CNY', symbol: '¥' },
  { name: 'COP', symbol: '$' },
  { name: 'CRC', symbol: '₡' },
  { name: 'CUC', symbol: '$' },
  { name: 'CUP', symbol: '₱' },
  { name: 'CVE', symbol: '$' },
  { name: 'CZK', symbol: 'Kč' },
  { name: 'DJF', symbol: 'Fdj' },
  { name: 'DKK', symbol: 'kr' },
  { name: 'DOP', symbol: 'RD$' },
  { name: 'DZD', symbol: 'دج' },
  { name: 'EEK', symbol: 'kr' },
  { name: 'EGP', symbol: '£' },
  { name: 'ERN', symbol: 'Nfk' },
  { name: 'ETB', symbol: 'Br' },
  { name: 'ETH', symbol: 'Ξ' },
  { name: 'EUR', symbol: '€' },
  { name: 'FJD', symbol: '$' },
  { name: 'FKP', symbol: '£' },
  { name: 'GBP', symbol: '£' },
  { name: 'GEL', symbol: '₾' },
  { name: 'GGP', symbol: '£' },
  { name: 'GHC', symbol: '₵' },
  { name: 'GHS', symbol: 'GH₵' },
  { name: 'GIP', symbol: '£' },
  { name: 'GMD', symbol: 'D' },
  { name: 'GNF', symbol: 'FG' },
  { name: 'GTQ', symbol: 'Q' },
  { name: 'GYD', symbol: '$' },
  { name: 'HKD', symbol: '$' },
  { name: 'HNL', symbol: 'L' },
  { name: 'HRK', symbol: 'kn' },
  { name: 'HTG', symbol: 'G' },
  { name: 'HUF', symbol: 'Ft' },
  { name: 'IDR', symbol: 'Rp' },
  { name: 'ILS', symbol: '₪' },
  { name: 'IMP', symbol: '£' },
  { name: 'INR', symbol: '₹' },
  { name: 'IQD', symbol: 'ع.د' },
  { name: 'IRR', symbol: '﷼' },
  { name: 'ISK', symbol: 'kr' },
  { name: 'JEP', symbol: '£' },
  { name: 'JMD', symbol: 'J$' },
  { name: 'JOD', symbol: 'JD' },
  { name: 'JPY', symbol: '¥' },
  { name: 'KES', symbol: 'KSh' },
  { name: 'KGS', symbol: 'лв' },
  { name: 'KHR', symbol: '៛' },
  { name: 'KMF', symbol: 'CF' },
  { name: 'KPW', symbol: '₩' },
  { name: 'KRW', symbol: '₩' },
  { name: 'KWD', symbol: 'KD' },
  { name: 'KYD', symbol: '$' },
  { name: 'KZT', symbol: 'лв' },
  { name: 'LAK', symbol: '₭' },
  { name: 'LBP', symbol: '£' },
  { name: 'LKR', symbol: '₨' },
  { name: 'LRD', symbol: '$' },
  { name: 'LSL', symbol: 'M' },
  { name: 'LTC', symbol: 'Ł' },
  { name: 'LTL', symbol: 'Lt' },
  { name: 'LVL', symbol: 'Ls' },
  { name: 'LYD', symbol: 'LD' },
  { name: 'MAD', symbol: 'MAD' },
  { name: 'MDL', symbol: 'lei' },
  { name: 'MGA', symbol: 'Ar' },
  { name: 'MKD', symbol: 'ден' },
  { name: 'MMK', symbol: 'K' },
  { name: 'MNT', symbol: '₮' },
  { name: 'MOP', symbol: 'MOP$' },
  { name: 'MRO', symbol: 'UM' },
  { name: 'MRU', symbol: 'UM' },
  { name: 'MUR', symbol: '₨' },
  { name: 'MVR', symbol: 'Rf' },
  { name: 'MWK', symbol: 'MK' },
  { name: 'MXN', symbol: '$' },
  { name: 'MYR', symbol: 'RM' },
  { name: 'MZN', symbol: 'MT' },
  { name: 'NAD', symbol: '$' },
  { name: 'NGN', symbol: '₦' },
  { name: 'NIO', symbol: 'C$' },
  { name: 'NOK', symbol: 'kr' },
  { name: 'NPR', symbol: '₨' },
  { name: 'NZD', symbol: '$' },
  { name: 'OMR', symbol: '﷼' },
  { name: 'PAB', symbol: 'B/.' },
  { name: 'PEN', symbol: 'S/.' },
  { name: 'PGK', symbol: 'K' },
  { name: 'PHP', symbol: '₱' },
  { name: 'PKR', symbol: '₨' },
  { name: 'PLN', symbol: 'zł' },
  { name: 'PYG', symbol: 'Gs' },
  { name: 'QAR', symbol: '﷼' },
  { name: 'RMB', symbol: '¥' },
  { name: 'RON', symbol: 'lei' },
  { name: 'RSD', symbol: 'Дин.' },
  { name: 'RUB', symbol: '₽' },
  { name: 'RWF', symbol: 'R₣' },
  { name: 'SAR', symbol: '﷼' },
  { name: 'SBD', symbol: '$' },
  { name: 'SCR', symbol: '₨' },
  { name: 'SDG', symbol: 'ج.س.' },
  { name: 'SEK', symbol: 'kr' },
  { name: 'SGD', symbol: '$' },
  { name: 'SHP', symbol: '£' },
  { name: 'SLL', symbol: 'Le' },
  { name: 'SOS', symbol: 'S' },
  { name: 'SRD', symbol: '$' },
  { name: 'SSP', symbol: '£' },
  { name: 'STD', symbol: 'Db' },
  { name: 'STN', symbol: 'Db' },
  { name: 'SVC', symbol: '$' },
  { name: 'SYP', symbol: '£' },
  { name: 'SZL', symbol: 'E' },
  { name: 'THB', symbol: '฿' },
  { name: 'TJS', symbol: 'SM' },
  { name: 'TMT', symbol: 'T' },
  { name: 'TND', symbol: 'د.ت' },
  { name: 'TOP', symbol: 'T$' },
  { name: 'TRL', symbol: '₤' },
  { name: 'TRY', symbol: '₺' },
  { name: 'TTD', symbol: 'TT$' },
  { name: 'TVD', symbol: '$' },
  { name: 'TWD', symbol: 'NT$' },
  { name: 'TZS', symbol: 'TSh' },
  { name: 'UAH', symbol: '₴' },
  { name: 'UGX', symbol: 'USh' },
  { name: 'USD', symbol: '$' },
  { name: 'UYU', symbol: '$U' },
  { name: 'UZS', symbol: 'лв' },
  { name: 'VEF', symbol: 'Bs' },
  { name: 'VND', symbol: '₫' },
  { name: 'VUV', symbol: 'VT' },
  { name: 'WST', symbol: 'WS$' },
  { name: 'XAF', symbol: 'FCFA' },
  { name: 'XBT', symbol: 'Ƀ' },
  { name: 'XCD', symbol: '$' },
  { name: 'XOF', symbol: 'CFA' },
  { name: 'XPF', symbol: '₣' },
  { name: 'YER', symbol: '﷼' },
  { name: 'ZAR', symbol: 'R' },
  { name: 'ZWD', symbol: 'Z$' },
];

export default currencyList;
Enter fullscreen mode Exit fullscreen mode

Now, Open index.ts under src/index.ts from the root.

And change the code from

export const sum = (a: number, b: number) => {
  if ('development' === process.env.NODE_ENV) {
    console.log('boop');
  }
  return a + b;
};
Enter fullscreen mode Exit fullscreen mode

to

import currencyList from './currencyList';

export const getCurrencySymbol = (currencyCode: string) => {
  if (
    currencyCode === '' ||
    currencyCode === undefined ||
    currencyCode === null ||
    currencyCode === ' '
  ) {
    console.log('Enter a valid currency code');
  } else {
    for (let i = 0; i < currencyList.length; i++) {
      if (currencyList[i].name === currencyCode) {
        return currencyList[i].symbol;
      }
    }
  }
};

Enter fullscreen mode Exit fullscreen mode

Lets understand what are we really doing, we are importing the currencyList, then we are exporting a arrow function getCurrencySymbol which accepts currencyCode as an argument.

Then we are checking for null, empty-string, undefined or string with white space in the if statement.

Now if the currency code entered is correct then we will use a For loop for checking against the currencyCode in our currencyList and returning the corresponding symbol.

And thats all for the coding part, Give yourself a pat if you have done this much.

BONUS 🔥

We are ready for publishing our package but before that we will test it. Yes we will be testing it using jest.

Go to test directory and delete all the files, we are pro we will build our own test from scratch.

Create a currency.test.ts file in the test directory. And write the code.

import { getCurrencySymbol } from '../src';

describe('Symbol-Check', () => {
  it('works', () => {
    expect(getCurrencySymbol('INR')).toEqual('₹');
  });
});
Enter fullscreen mode Exit fullscreen mode

Here we are checking if our function is working, and for that we have created a test named Symbol-Check and we are passing INR as our currency code and expecting symbol, and if this happens our test will get pass.

Now run

yarn test
Enter fullscreen mode Exit fullscreen mode

And you will see a test pass successful message.

Let's publish our package.

But before it we need to change few configuration in our tsconfig.json.

Change the noImplicitReturns to false in the tsconfig.json. Why we are doing it ? You can check this at - Here

Your tsconfig.json should look like this-

{
  // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs
  "include": ["src", "types"],
  "compilerOptions": {
    "module": "esnext",
    "lib": ["dom", "esnext"],
    "importHelpers": true,
    // output .d.ts declaration files for consumers
    "declaration": true,
    // output .js.map sourcemap files for consumers
    "sourceMap": true,
    // match output dir to input dir. e.g. dist/index instead of dist/src/index
    "rootDir": "./src",
    // stricter type-checking for stronger correctness. Recommended by TS
    "strict": true,
    // linter checks for common issues
    "noImplicitReturns": false,
    "noFallthroughCasesInSwitch": true,
    // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    // use Node's module resolution algorithm, instead of the legacy TS one
    "moduleResolution": "node",
    // transpile JSX to React.createElement
    "jsx": "react",
    // interop between ESM and CJS modules. Recommended by TS
    "esModuleInterop": true,
    // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS
    "skipLibCheck": true,
    // error out if import and file system have a casing mismatch. Recommended by TS
    "forceConsistentCasingInFileNames": true,
    // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc`
    "noEmit": true
  }
}
Enter fullscreen mode Exit fullscreen mode

Now let's publish our package.

You just need to run one command to publish your package.

npm run publish
Enter fullscreen mode Exit fullscreen mode

🎉 Hurray You just published your typescript package on npm. 🥳

Code - https://github.com/Anishpras/currency-symbol-generator

Website - www.anishprashun.com

LinkedIn - https://www.linkedin.com/in/anishpras118

Twitter - https://twitter.com/APrashun

Oldest comments (0)