You may have worked with TypeScript before when using a starter project or a tool like the Angular CLI. In this tutorial, you will learn how to set up a TypeScript project without a starter’s help. You will also learn how compiling works in TypeScript and how to use a linter with your TypeScript project. This guide will walk you through how to set up TypeScript project configurations from scratch, initialize TypeScript project files, and create new TypeScript project workflows.
Deploy your frontend applications from GitHub using DigitalOcean App Platform. Let DigitalOcean focus on scaling your app.
Install TypeScript locally and initialize your project:
Begin by installing TypeScript as a development dependency in your project using npm i typescript --save-dev
. This ensures that everyone working on the project uses the same TypeScript version. Next, initialize your project with npx tsc --init
, which creates a tsconfig.json
file. This file is essential for configuring how TypeScript compiles your code and helps maintain consistency across different environments.
Leverage tsconfig.json
for precise compilation control:
The tsconfig.json
file is the heart of your TypeScript configuration. Here, you can specify important options such as rootDir
(where your source files live), outDir
(where compiled JavaScript will be output), strict
(to enable strict type-checking for safer code), and esModuleInterop
(to improve compatibility with CommonJS modules). Customizing these settings tailors the TypeScript compiler to your project’s structure and requirements.
Compile efficiently with npx tsc
and watch mode:
To convert your TypeScript files into JavaScript, use the npx tsc
command. For a smoother development experience, you can enable watch mode with npx tsc -w
, which automatically recompiles your code whenever you save changes. This immediate feedback loop helps you catch errors early and speeds up your workflow, making development more productive and less error-prone.
Integrate Google TypeScript Style (GTS) for robust linting and standards:
By applying the Google TypeScript Style (GTS) package, you instantly add a comprehensive linting setup and a set of opinionated defaults to your project. GTS enforces best practices and code consistency, reducing the need for manual configuration. This allows you to focus on writing quality code while ensuring your project adheres to widely accepted TypeScript standards from the start.
Before you begin working through this tutorial, make sure you have the following in place:
Node.js (latest version):
Ensure that you have the most up-to-date version of Node.js installed on your computer. Node.js is the JavaScript runtime that TypeScript builds upon, and having the latest version will help you avoid compatibility issues and take advantage of the newest features. If you need guidance on installing Node.js or setting up your local development environment, refer to our comprehensive guide: How to Install Node.js and Create a Local Development Environment.
Basic familiarity with npm (Node Package Manager):
You should be comfortable using npm
, which is included automatically when you install Node.js. npm
is essential for managing project dependencies, installing packages, and running scripts in your TypeScript project. If you are new to npm
or want to deepen your understanding, we recommend reading: How To Use Node.js Modules with npm
and package.json
.
Having these prerequisites in place will ensure a smooth experience as you follow along with the steps in this tutorial. If you are missing either of these, please take a moment to review the linked resources before proceeding.
These steps are validated on Ubuntu 24.04 LTS (Noble), 22.04 LTS (Jammy), and 20.04 LTS (Focal). If you’re on 18.04 or earlier (now end‑of‑life), upgrade to a supported release before proceeding. See Upgrading Ubuntu LTS for step‑by‑step paths
If you want to bootstrap everything in one go, you can use this one-liner to set up your TypeScript starter project with common tools:
npm init -y && npm i -D typescript ts-node eslint prettier @types/node && npx tsc --init
This command will initialize a new TypeScript project, install TypeScript and supporting developer tools, and generate a tsconfig.json
file. It’s a fast way to create a new TypeScript project without missing any essentials.
Here are some of the most commonly used options you can configure in your tsconfig.json
:
Option | Purpose |
---|---|
target |
Specifies the JavaScript version to compile to (e.g., ES6, ES2020). |
module |
Defines the module system (e.g., CommonJS, ESNext). |
moduleResolution |
Determines how modules are resolved (commonly set to node ). |
rootDir |
The root folder of your TypeScript source files (e.g., ./src ). |
outDir |
The output folder for compiled JavaScript files (e.g., ./build ). |
strict |
Enables all strict type-checking options for safer code. |
esModuleInterop |
Improves compatibility with CommonJS modules when using ES module syntax. |
These options form the backbone of most TypeScript project setups and can be customized based on your needs.
# One-liner to initialize a new TypeScript project
mkdir typescript-project && cd typescript-project
npm i -D typescript
npx tsc --init
Create and enter your project directory:
mkdir typescript-project
cd typescript-project
Install TypeScript as a development dependency:
npm i -D typescript
The --save-dev
flag ensures TypeScript is only required for development.
Initialize your TypeScript project:
npx tsc --init
This creates a tsconfig.json
file with default configuration.
Open tsconfig.json
in your editor to review and customize options:
nano tsconfig.json
Most options are commented out by default. For example:
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
// ... (lots of commented-out options)
}
}
Adjust configuration as needed, such as setting "outDir": "./build"
to control where compiled files go.
Note: Step 3 will later replace many configurations with opinionated defaults, but this setup gets you started quickly.
# Create your main TypeScript file
echo "const world = 'world';
export function hello(who: string = world): string {
return \`Hello \${who}!\`;
}
" > index.ts
# Compile TypeScript project
npx tsc
Write your TypeScript code in index.ts
:
const world = 'world';
export function hello(who: string = world): string {
return `Hello ${who}!`;
}
Compile your code:
npx tsc
This generates compiled JavaScript in the build
folder (if outDir
is set).
typescript-project/
├── build/
│ ├── index.js
│ └── index.js.map
├── index.ts
└── tsconfig.json
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hello = void 0;
const world = 'world';
function hello(who = world) {
return `Hello ${who}!`;
}
exports.hello = hello;
node build/index.js
(no output, unless you invoke the function; add below for demo)
To get output, update your index.ts
with:
console.log(hello());
Then recompile and run:
npx tsc
node build/index.js
Expected output:
Hello world!
npx tsc -w
This recompiles your code on every save.
# Install Google TypeScript Style (GTS)
npm install --save-dev gts
# Initialize GTS in your project
npx gts init
# Compile and check for lint errors
npm run compile
npm run check
Bad Code (with lint error):
function sayhi(name:string){console.log('Hi, '+name)}
Run lint check:
npm run check
index.ts:1:10: Missing space before function parentheses.
index.ts:1:20: Missing space after colon.
index.ts:1:47: Missing semicolon.
Found 3 errors.
function sayHi(name: string) {
console.log('Hi, ' + name);
}
GTS provides a style guide, linter, and code corrector in one. It bootstraps your project with opinionated defaults, including a tsconfig.json
, ESLint config, and npm scripts:
npm run compile
— Compile your TypeScript code.npm run check
— Check for lint/style errors.npm run fix
— Auto-fix lint problems.To customize rules, extend the ESLint config:
---
extends:
- './node_modules/gts'
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build",
"strict": true,
"esModuleInterop": true,
"module": "nodenext",
"moduleResolution": "node",
"skipLibCheck": true,
"noUncheckedIndexedAccess": true
}
}
module: "nodenext"
vs commonjs
:"nodenext"
for projects targeting ES modules in Node.js (Node 16+). Use "commonjs"
for classic Node.js projects or older compatibility.moduleResolution: "node"
vs "bundler"
:"node"
mimics Node.js resolution logic, best for server-side and most projects."bundler"
is for front-end projects using tools like Vite or Webpack, which handle resolution differently.skipLibCheck
:true
to speed up builds by skipping type checks on libraries in node_modules
.noUncheckedIndexedAccess
:undefined
unless checked.src/
, output in build/
or dist/
.camelCase
for variables/functions, PascalCase
for classes/types."strict": true
for robust type-checking.TypeScript is commonly used in these scenarios:
npm i express @types/express @types/node
Installs Express plus TypeScript typings for Express and Node so the compiler recognizes framework APIs and Node globals during development.
// index.ts
import express from 'express';
const app = express();
app.get('/', (req, res) => res.send('Hello from Express + TypeScript!'));
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
This defines a minimal HTTP server that handles GET /
and listens on port 3000
.
package.json
:"scripts": {
"dev": "ts-node index.ts"
}
This dev
script runs the app with ts-node
, so you can iterate without a separate build step.
npx ts-node index.ts
# or
npm run dev
If you see an “address already in use” error, change app.listen(3000)
to another free port (for example, 3001
) and rerun.
npx create-react-app my-app --template typescript
# or with Vite:
npm create vite@latest my-app -- --template react-ts
type GreetingProps = { name: string };
const Greeting: React.FC<GreetingProps> = ({ name }) => (
<div>Hello, {name}!</div>
);
"declaration": true
in tsconfig.json
to generate .d.ts
files for consumers.When setting up or working with TypeScript, beginners often run into a few common issues. Here are some errors you might encounter and how to fix them:
require
in a TypeScript file without Node.js types. Fix it by installing @types/node
and ensuring "moduleResolution": "node"
is set in your tsconfig.json
."module": "commonjs"
in tsconfig.json
or running Node with --experimental-modules
.npm i -D @types/node
."esModuleInterop": true
in your tsconfig.json
.ts-node
fails with type errors, make sure your tsconfig.json
is configured correctly, that you have the right version of TypeScript, and try running with npx ts-node --transpile-only
if you only want to bypass type checking at runtime.You can initialize a new TypeScript project with:
npm init -y
npm i -D typescript
npx tsc --init
tsconfig.json
configures how TypeScript compiles your code—options like target JavaScript version, module system, root directory, and output directory.
Installing locally (npm i -D typescript
) is recommended so all team members use the same version. You can install globally if you need tsc
everywhere.
Use ts-node
, which runs .ts
files directly:
npx ts-node index.ts
tsc
: Compiles TypeScript into JavaScript files.ts-node
: Runs TypeScript files directly without creating separate .js
outputs.Yes. For React, you can scaffold a new project with:
npx create-react-app my-app --template typescript
For Express, install @types/express
and use TypeScript for type safety in backend development.
Beyond traditional TypeScript projects, you can also use TypeScript to build powerful servers that interact directly with LLMs using the Model Context Protocol (MCP) TypeScript SDK. MCP is a standardized way to expose resources, tools, and prompts so that AI systems can consume them reliably.
The MCP TypeScript SDK makes it easy to:
This allows you to build TypeScript-powered servers that securely provide functionality to LLM-based applications.
Install the MCP SDK via npm:
npm install @modelcontextprotocol/sdk
Requires Node.js v18 or higher.
Here’s a simple MCP server that provides a calculator tool and a dynamic greeting resource:
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
// Create an MCP server
const server = new McpServer({
name: 'demo-server',
version: '1.0.0'
});
// Register an addition tool
server.registerTool(
'add',
{
title: 'Addition Tool',
description: 'Add two numbers',
inputSchema: { a: z.number(), b: z.number() }
},
async ({ a, b }) => ({
content: [{ type: 'text', text: String(a + b) }]
})
);
// Register a dynamic greeting resource
server.registerResource(
'greeting',
new ResourceTemplate('greeting://{name}', { list: undefined }),
{
title: 'Greeting Resource',
description: 'Dynamic greeting generator'
},
async (uri, { name }) => ({
contents: [
{
uri: uri.href,
text: `Hello, ${name}!`
}
]
})
);
// Start transport via stdio
const transport = new StdioServerTransport();
await server.connect(transport);
npx ts-node server.ts
Expected output:
MCP server started and listening for requests via stdio...
MCP treats servers like APIs for LLMs:
This approach lets you build AI-powered applications in TypeScript that are composable, testable, and standards-compliant.
For further documentation, see the official MCP docs and the TypeScript SDK repository.
This guide showed how to set up a new TypeScript project, configure tsconfig.json
with modern best practices, compile and run code, and enforce code standards with Google TypeScript Style (GTS). You also learned how to structure Node.js/Express and React projects with TypeScript, and how to build an MCP server.
TypeScript’s adoption is growing rapidly (2024 Stack Overflow Developer Survey), and it is increasingly common in large-scale and AI-assisted development.
Continue learning:
For more details on configuration, see the TypeScript tsconfig.json documentation.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Thanks for the introduction to TS. I noticed however that TSlint is deprecated since 2019, maybe rewrite the instructions with steps to get things set up with eslint?
At the npx tsc index.ts
step, I think you meant to just run npx tsc
without the index.ts.
If you do it with the index.ts then it won’t create the dist folder. At least it didn’t for me.
when i run npx tsc -w
it tells that Parameter ‘world’ cannot reference itself.
Hello, we can also use the cli-tool:
$ npx create-typescript-application
Cheers!
great writing. you are missing a step “npm init” after the directory creation
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.