What you will build
You will calculate the total for three items priced at 12.50 each and print Total: 37.50. This small terminal program keeps the focus on the TypeScript workflow: create a project, check source code, turn it into JavaScript, then run that JavaScript with Node.js.
You need a supported Node.js installation with npm. Follow the setup guide for your operating system if node --version or npm --version does not work. This tutorial uses the normal Node.js/npm workflow; it does not ask Node to execute a .ts file directly.
1. Create the project and install TypeScript
Open PowerShell on Windows or a terminal on macOS or Linux in a directory where you can make a project. mkdir creates the folder and cd enters it. npm init -y writes a starter package.json with default answers. npm install --save-dev typescript records TypeScript as a local development dependency and creates or updates package-lock.json. npx tsc --version shows which installed compiler this project will use.
Node.js will run the compiled program later. npm downloads the compiler; npm does not itself run your TypeScript source. If installation fails, check that Node and npm have version numbers and that you have network access.
Create an npm project with a local TypeScript compiler
node --version
npm --version
mkdir typescript-receipt
cd typescript-receipt
npm init -y
npm install --save-dev typescript
npx tsc --version
mkdir src2. Configure the compiler
Run npx tsc --init inside typescript-receipt. It creates tsconfig.json. Generated defaults change between TypeScript releases, so open that file and replace its contents with the configuration below for this tutorial. Save it next to package.json.
include chooses .ts files in src. rootDir keeps the source tree rooted there; outDir puts generated JavaScript in dist. strict enables stronger type checks, and noEmitOnError prevents this compilation from writing output when it reports errors. target selects the JavaScript language level. The default package made by npm init -y has no "type": "module" field, so CommonJS is a simple matching format for this Node example. Other projects may need different module settings.
Initialise compiler settings
npx tsc --initSave as tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"rootDir": "src",
"outDir": "dist",
"strict": true,
"noEmitOnError": true
},
"include": ["src/**/*.ts"]
}3. Write and check a basic program
In your editor, save the code below as src/receipt.ts. A .ts file can begin with familiar JavaScript: TypeScript infers that unitPrice and quantity are numbers from their values. Multiplying them gives 37.5. toFixed(2) turns that number into a two-decimal string for display, so console.log prints Total: 37.50.
Run the check command from the project root. The --project option tells tsc to use tsconfig.json and its include setting. --noEmit asks for diagnostics without creating dist. If you see no output and the command exits successfully, this version passed the type check; it does not mean the program has run.
Save as src/receipt.ts: first version
const unitPrice = 12.5;
const quantity = 3;
const total = unitPrice * quantity;
console.log(`Total: ${total.toFixed(2)}`);Check the project without generating JavaScript
npx tsc --project tsconfig.json --noEmit4. Add type annotations
Replace src/receipt.ts with the typed version below. The function calculates a total from a price and quantity. Each : number on a parameter tells the checker which kind of input that parameter expects; the : number after the parameter list describes the result. The two variable annotations are explicit practice, although TypeScript could infer those types from 12.5 and 3.
The return statement multiplies the inputs. The call passes both variables into the function, then toFixed(2) formats the returned number for the output message. Type annotations help the checker, but they are removed from the compiled JavaScript and do not validate data at runtime.
Save as src/receipt.ts: typed version
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
const unitPrice: number = 12.5;
const quantity: number = 3;
const total = calculateTotal(unitPrice, quantity);
console.log(`Total: ${total.toFixed(2)}`);5. Find and correct a type error
Temporarily replace only the calculateTotal call with the incorrect call below. The second argument is now the string "3" rather than the number held in quantity. Run the noEmit check again. TypeScript reports TS2345 because a string cannot be passed to the quantity: number parameter. The compiler reports a problem with your source before Node runs anything.
Replace that call with the corrected version below and run the noEmit check again. It should finish without diagnostics. Do not treat an old dist/receipt.js from a previous successful build as evidence that the broken source compiled; noEmitOnError prevents new output on error but does not delete old files.
Temporarily change the call to this
calculateTotal(unitPrice, "3")Check and observe the TS2345 diagnostic
npx tsc --project tsconfig.json --noEmitCorrect the call
calculateTotal(unitPrice, quantity)Check the corrected source
npx tsc --project tsconfig.json --noEmit6. Compile and run the JavaScript
Now run the compiler without --noEmit. It checks the corrected source and writes dist/receipt.js. Open that output file if you want to inspect it: the number annotations are gone, while the multiplication and console.log call remain. Run the generated .js file with Node.js; do not substitute node src/receipt.ts for this workflow.
The terminal prints Total: 37.50. The program multiplies 12.5 by 3 to get the number 37.5; toFixed(2) produces the text 37.50, which is inserted into the message. toFixed is a simple display demonstration, not a general solution for money calculations that require exact decimal arithmetic or currency rules.
Compile the project and run the emitted file
npx tsc --project tsconfig.json
node dist/receipt.jsExpected terminal output
Total: 37.50Files you should now have
After a successful compile, the project contains the files below. TypeScript creates dist/receipt.js; you create src/receipt.ts and tsconfig.json. npm creates package.json and package-lock.json. node_modules contains installed dependencies and is usually not committed to version control.
If dist/receipt.js is missing, confirm that you saved src/receipt.ts, are in the project root and ran the compiler without --noEmit. Read any diagnostic before trying node dist/receipt.js.
Project structure after compilation
typescript-receipt/
├─ package.json
├─ package-lock.json
├─ tsconfig.json
├─ src/
│ └─ receipt.ts
├─ dist/
│ └─ receipt.js
└─ node_modules/Practise the full cycle
Change the quantity to 4 and predict the new output before running the check, compile and Node commands again. Then try passing a string to calculateTotal once more and explain why the check fails. TypeScript helps catch this kind of mismatch before execution, but you still need runtime tests for behaviour and validation for untrusted input.
Syntax
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
const unitPrice: number = 12.5;
const quantity: number = 3;
const total = calculateTotal(unitPrice, quantity);
console.log(`Total: ${total.toFixed(2)}`);Examples
The corrected receipt calculator
The final src/receipt.ts file. In a local project, type-check and compile it before running dist/receipt.js with Node.
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
const unitPrice: number = 12.5;
const quantity: number = 3;
const total = calculateTotal(unitPrice, quantity);
console.log(`Total: ${total.toFixed(2)}`);- calculateTotal expects two numbers and returns their product. The annotations make those expectations visible to TypeScript before the program runs.
- unitPrice is 12.5 and quantity is 3. Passing both numbers gives a total of 37.5. Passing "3" instead triggers TS2345 during a full project check.
- toFixed(2) formats 37.5 as the string 37.50; the template literal adds Total: before it. The compiled JavaScript prints Total: 37.50 in Node or a compatible preview.
- A preview that only transpiles TypeScript does not replace npx tsc --project tsconfig.json --noEmit. Use the local checker to verify the typed call, then run the emitted JavaScript.
Best practices
- Install the compiler in the project and use npx tsc so the recorded version is used.
- Keep source files separate from generated JavaScript and run the output with Node.js.
- Check types before compiling and resolve diagnostics rather than ignoring them.
- Test runtime results as well as type-checking, especially with input from users or APIs.
Runtime & versions
Compiled to JavaScript. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
TypeScript Handbook