I set out recently to get more fluent in TypeScript, and after getting comfortable with syntax in browser-based interpreters, the next step was to get TypeScript running locally. As this is generally useful information, I figured I would write a blog post to share my approach.
Global ts-node Install
Assuming you already have the npm
package installed, run the following command to globally install the ts-node
package:
sudo npm install --global ts-node
Further, if you’re setting this up in your personal dotfiles, be sure to put this install in an appropriate place in your pipeline. (I have an .npm
script in my dotfiles that is run the first time I set them up, for example.)
Note that we’re not installing TypeScript itself globally. Instead, we’ll set it as a project dependency so that different TypeScript versions can be supported across different projects.
Set NPM Configuration Default
You can also configure default options that will be automatically set when you generate a new Node project:
npm config set init-author-name "Your Name" npm config set init-author-email "youremail@email.com" npm config set init-author-url "https://github.com/yourgithubhandle" npm config set init-license "MIT" npm config set init-version "0.0.1"
Node/TypeScript Project Initialization
Create a new, empty directory and cd
into it. The following commands will set up a new Node project with some useful defaults:
yes | npx gitignore node npm init -y npm i --save-dev typescript git init mkdir src touch src/index.ts
The above code block will:
- Create a .gitignore file with standard Node-project settings
- Create a package.json and package-lock.json reflecting all of the defaults we set earlier
- Set TypeScript as a dev dependency and add it to package*.json files
- Initialize a git repository
- Create an empty directory and file at
src/index.ts
One more step: create a tsconfig.json
. This method allows us to write a beautifully formatted JSON block within our script, but also messes up my beautifully formatted script by requiring no white space at the beginning of certain lines, most notably the closing EOF
statement.
tsconfig_content=$(cat <<EOF { "compilerOptions": { "target": "es6", "module": "commonjs", "outDir": "./dist", "rootDir": "./src", "strict": true } } EOF ) echo "$tsconfig_content" > tsconfig.json
Bonus Content: Project Directory Creation
I was not a fan of having to manually create a folder to run the above commands in.
if [ ! -z "$(ls -A)" ]; then echo "WARNING: Current working directory is not empty, see the contents:" ls -A read -p "Directory name to create in ~/projects/ (leave blank to proceed in cwd): " project_name if [ -n "$project_name" ]; then local location="$HOME/projects/$project_name" mkdir -p "$location" echo "Project directory created at: $location" cd "$location" fi fi
This block checks if the current directory is empty. If it is: great, we move on. Otherwise, it will prompt for a project_name
. I like to keep all of my projects in a directory at ~/projects
, so my code creates a new directory with the project_name
in that location.
Alternatively, we retain the option to not provide a project name. This is for cases where we have a file or two already created but we still want to initialize a Node project in that directory.
Bonus Content: Directory Safeguards
With the ability to run in non-empty directories, I wanted to add a couple safeguards so that I didn’t run this in undesirable places and be forced to clean up the mess.
if [[ $(pwd) = "$HOME/projects" || $(pwd) = $HOME ]]; then echo "ERROR: Don't run this script in $HOME or $HOME/projects" return fi
Because ~
and ~/projects
are meaningful directories for me, I don’t want to proceed with the script if they are the cwd.
if [[ -d ".git" ]]; then echo "ERROR: A .git folder already exists in the current working directory" return fi
We’re also aborting the mission if the cwd is already a git repository.
The Full Script
Here is my current working version of node_project_init.sh
:
#!/bin/bash # Spin up some basic Node project files, with a little bit of prompting # and safeguarding to make sure we're not running in undesirable places function node_project_init { if [ ! -z "$(ls -A)" ]; then echo "WARNING: Current working directory is not empty, see the contents:" ls -A read -p "Directory name to create in ~/projects/ (leave blank to proceed in cwd): " project_name if [ -n "$project_name" ]; then local location="$HOME/projects/$project_name" mkdir -p "$location" echo "Project directory created at: $location" cd "$location" fi fi if [[ $(pwd) = "$HOME/projects" || $(pwd) = $HOME ]]; then echo "ERROR: Don't run this script in $HOME or $HOME/projects" return fi if [[ -d ".git" ]]; then echo "ERROR: A .git folder already exists in the current working directory" return fi yes | npx gitignore node npm init -y npm i --save-dev typescript git init mkdir src touch src/index.ts tsconfig_content=$(cat <<EOF { "compilerOptions": { "target": "es6", "module": "commonjs", "outDir": "./dist", "rootDir": "./src", "strict": true } } EOF ) echo "$tsconfig_content" > tsconfig.json }
Sweet!
Installing for Use
To make the command node_project_init
available in your terminal, do the following.
Update your PATH
environment variable in your ~/.bashrc
file or wherever else you prefer:
export PATH="$HOME/path/to/directory/with/script:$PATH"
Then source
the script (you’ll need to do this whenever making changes to update the command in your terminal):
source $HOME/path/to/directory/with/script/node_project_init.sh
Now you can run node_project_init
from any location in your system!
Running Code
Add some TypeScript to src/index.ts
. Here’s a sample program if you’d like:
function helloName(name: string): void { console.log(`Hey, ${name}!`) } helloName("you")
Remember how way up at the top we did a global install of ts-node
? This is where that comes in, as it allows you to run your TypeScript file directly:
ts-node src/index.ts
The alternative to this is running the tsc
command, which transpiles your TypeScript code to ES6 (based on the settings from earlier), then you could run node distro/index.js
after transpiling. The ts-node
option is a useful shortcut!
Hope this was helpful! Cheers.