๐ TypeScript Basics
๐ Definitionโ
TypeScript is a superset language of JavaScript developed by Microsoft. By adding a static type system to JavaScript, it detects errors at code writing time and enhances IDE autocomplete functionality. TypeScript code is compiled and converted to JavaScript for execution.
๐ฏ Understanding Through Analogiesโ
Contract Analogyโ
Comparing TypeScript to a contract:
JavaScript (Verbal Promise)
A: "Let's meet tomorrow afternoon!"
B: "Okay, got it!"
The next day...
A: "Why didn't you come?"
B: "I thought it was 2 PM?"
A: "No, I said 5 PM!"
Problems:
- No specific time specified
- Misunderstanding occurs
- Problem discovered at execution time
---
TypeScript (Formal Contract)
Contract:
- Date: January 15, 2024
- Time: 5 PM sharp
- Location: Gangnam Station Exit 2
- Participants: A, B (types specified!)
Advantages:
- Clear agreement
- No misunderstanding possible
- Verified at contract writing time
- Legal effect
Factory Analogyโ
JavaScript Factory (No Inspection)
Parts Receiving:
- Any part is OK
- No size check
- No standard check
Assembly Line:
- Problems discovered during assembly
- "This screw doesn't fit?"
- "This part size is strange?"
Result:
- Defective products
- Time/cost waste
- Customer complaints
---
TypeScript Factory (Strict Inspection)
Parts Receiving:
โ Size measurement
โ Standard check
โ Quality inspection
โ Defective parts rejected
Assembly Line:
- Parts fit exactly
- Assembly without problems
- Fast production
Result:
- High-quality products
- Efficient production
- Customer satisfaction
LEGO Block Analogyโ
JavaScript LEGO
- Can try fitting any block
- Only know if it fits by trying
- Confusing when building large creations
TypeScript LEGO
- Each block has a label
- "This is a 2x4 block"
- "Only 2x4 fits in this hole"
- Can't fit what doesn't match from the start
Advantages:
- Assemble accurately following instructions
- Prevent mistakes
- No problem even with large creations
โ๏ธ How It Worksโ
1. Static Type Systemโ
// JavaScript (Dynamic Types)
let name = "John Kim";
name = 123; // OK! No problem
name = true; // OK! No problem
name = null; // OK! No problem
// Problem discovered during execution
function greet(person) {
return "Hello, " + person.name; // Don't know what person is
}
greet({ name: "John" }); // OK
greet("John"); // ๐ฅ Runtime Error!
greet(null); // ๐ฅ Runtime Error!
// TypeScript (Static Types)
let name: string = "John Kim";
name = 123; // โ Compile Error! (Type error)
name = true; // โ Compile Error!
name = null; // โ Compile Error!
// Specify function parameters and return type
function greet(person: { name: string }): string {
return "Hello, " + person.name;
}
greet({ name: "John" }); // โ
OK
greet("John"); // โ Compile Error! (Type error)
greet(null); // โ Compile Error!
// Advantages:
// 1. Errors discovered at code writing time
// 2. IDE autocomplete
// 3. Safe refactoring
// 4. Acts as documentation
2. Compilation Processโ
// TypeScript Code
// app.ts
interface User {
id: number;
name: string;
email: string;
}
function getUser(id: number): User {
return {
id: id,
name: "John Kim",
email: "kim@example.com"
};
}
const user: User = getUser(1);
console.log(user.name);
// โ TypeScript Compiler (tsc)
// JavaScript Code
// app.js
function getUser(id) {
return {
id: id,
name: "John Kim",
email: "kim@example.com"
};
}
var user = getUser(1);
console.log(user.name);
// Characteristics:
// 1. Type information removed
// 2. Can convert to ES5, ES6, ESNext, etc.
// 3. Runs in browser/Node.js
// 4. Source map generation (for debugging)
3. Type Inferenceโ
// TypeScript automatically infers types
// Explicit types
let name: string = "John Kim";
let age: number = 25;
// Type inference (automatic)
let name = "John Kim"; // Inferred as string
let age = 25; // Inferred as number
let isActive = true; // Inferred as boolean
// Arrays
let numbers = [1, 2, 3]; // Inferred as number[]
let names = ["Kim", "Lee"]; // Inferred as string[]
// Objects
let user = {
name: "John Kim",
age: 25
};
// Inferred as { name: string; age: number }
// Function return type
function add(a: number, b: number) {
return a + b; // Inferred as returning number
}
// Advantages:
// - Reduces type writing
// - Still type safe
// - Improves readability
๐ก Real Examplesโ
Basic Typesโ
// 1. Primitive types
let name: string = "John Kim";
let age: number = 25;
let isStudent: boolean = true;
let nothing: null = null;
let notDefined: undefined = undefined;
// 2. Arrays
let numbers: number[] = [1, 2, 3, 4, 5];
let names: Array<string> = ["John Kim", "Jane Lee"];
// Mixed arrays
let mixed: (number | string)[] = [1, "two", 3, "four"];
// 3. Tuples (fixed length, type for each position)
let person: [string, number] = ["John Kim", 25];
let coordinate: [number, number] = [10, 20];
// โ Wrong usage
person = [25, "John Kim"]; // Wrong order
person = ["John Kim"]; // Wrong length
person = ["John Kim", 25, true]; // Wrong length
// 4. enum (enumeration)
enum Color {
Red, // 0
Green, // 1
Blue // 2
}
let color: Color = Color.Red;
console.log(color); // 0
// Assigning values
enum Status {
Pending = "PENDING",
Approved = "APPROVED",
Rejected = "REJECTED"
}
let status: Status = Status.Pending;
console.log(status); // "PENDING"
// 5. any (allows all types)
let anything: any = "string";
anything = 123; // OK
anything = true; // OK
anything = null; // OK
// โ ๏ธ any removes TypeScript advantages!
// Use only when necessary
// 6. unknown (safer than any)
let value: unknown = "string";
// โ Cannot use directly
// console.log(value.length);
// โ
Use after type checking
if (typeof value === "string") {
console.log(value.length); // OK
}
// 7. void (no return value)
function logMessage(message: string): void {
console.log(message);
// no return
}
// 8. never (never returns)
function throwError(message: string): never {
throw new Error(message);
// Function never ends
}
function infiniteLoop(): never {
while (true) {
// Infinite loop
}
}
// 9. object
let obj: object = { name: "John Kim" };
let arr: object = [1, 2, 3];
let func: object = function() {};
Interfacesโ
// Interface: Define object structure
// 1. Basic interface
interface User {
id: number;
name: string;
email: string;
}
const user: User = {
id: 1,
name: "John Kim",
email: "kim@example.com"
};
// โ Missing property
const invalidUser: User = {
id: 1,
name: "John Kim"
// email missing!
};
// 2. Optional properties
interface Product {
id: number;
name: string;
price: number;
description?: string; // Optional (can exist or not)
}
const product1: Product = {
id: 1,
name: "Laptop",
price: 1000000,
description: "High-performance laptop"
};
const product2: Product = {
id: 2,
name: "Mouse",
price: 30000
// description OK even without it
};
// 3. Readonly properties
interface Config {
readonly apiUrl: string;
readonly timeout: number;
}
const config: Config = {
apiUrl: "https://api.example.com",
timeout: 5000
};
// โ Cannot modify
config.apiUrl = "https://api2.example.com";
// 4. Function types
interface SearchFunc {
(query: string, page: number): string[];
}
const search: SearchFunc = (query, page) => {
// Implementation
return ["Result1", "Result2"];
};
// 5. Index signature (dynamic properties)
interface StringMap {
[key: string]: string;
}
const translations: StringMap = {
hello: "Hello",
goodbye: "Goodbye",
thanks: "Thanks"
// Both key and value are string
};
// 6. Interface extension (inheritance)
interface Person {
name: string;
age: number;
}
interface Student extends Person {
studentId: string;
grade: number;
}
const student: Student = {
name: "John Kim",
age: 20,
studentId: "2024001",
grade: 2
};
// 7. Extending multiple interfaces
interface Printable {
print(): void;
}
interface Scannable {
scan(): void;
}
interface Printer extends Printable, Scannable {
model: string;
}
const printer: Printer = {
model: "HP-1234",
print() {
console.log("Printing...");
},
scan() {
console.log("Scanning...");
}
};
Type Aliasโ
// Type Alias: Naming types
// 1. Basic type alias
type UserID = number;
type UserName = string;
let id: UserID = 123;
let name: UserName = "John Kim";
// 2. Union types
type Status = "pending" | "approved" | "rejected";
let orderStatus: Status = "pending";
orderStatus = "approved"; // OK
// orderStatus = "shipped"; // โ Error
// 3. Object types
type Point = {
x: number;
y: number;
};
const point: Point = { x: 10, y: 20 };
// 4. Function types
type GreetFunction = (name: string) => string;
const greet: GreetFunction = (name) => {
return `Hello, ${name}!`;
};
// 5. Intersection types (intersection)
type Person = {
name: string;
age: number;
};
type Employee = {
employeeId: string;
department: string;
};
type EmployeePerson = Person & Employee;
const employee: EmployeePerson = {
name: "John Kim",
age: 30,
employeeId: "E123",
department: "Development"
// All properties required!
};
// 6. Interface vs Type
// Interface (extensible)
interface Animal {
name: string;
}
interface Animal {
age: number; // Merged!
}
const animal: Animal = {
name: "Dog",
age: 3
};
// Type (not extensible)
type Car = {
model: string;
};
// โ Error: Cannot duplicate declaration
// type Car = {
// year: number;
// };
// When to use which?
// - Interface: Object structure, classes, extensible
// - Type: Union, intersection, utility types
Genericsโ
// Generics: Reusable types
// โ Without generics (duplicate code)
function numberIdentity(value: number): number {
return value;
}
function stringIdentity(value: string): string {
return value;
}
function booleanIdentity(value: boolean): boolean {
return value;
}
// โ
Using generics (unified into one)
function identity<T>(value: T): T {
return value;
}
const num = identity<number>(123); // number
const str = identity<string>("hello"); // string
const bool = identity<boolean>(true); // boolean
// Even simpler with type inference
const num2 = identity(123); // Inferred as number
const str2 = identity("hello"); // Inferred as string
// 2. Generic arrays
function getFirstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
const firstNum = getFirstElement([1, 2, 3]); // number
const firstName = getFirstElement(["a", "b", "c"]); // string
// 3. Generic interfaces
interface Box<T> {
value: T;
}
const numberBox: Box<number> = { value: 123 };
const stringBox: Box<string> = { value: "hello" };
// 4. Generic classes
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
peek(): T | undefined {
return this.items[this.items.length - 1];
}
}
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
console.log(numberStack.pop()); // 3
const stringStack = new Stack<string>();
stringStack.push("a");
stringStack.push("b");
// 5. Generic constraints
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(item: T): void {
console.log(item.length);
}
logLength("hello"); // OK (string has length)
logLength([1, 2, 3]); // OK (array has length)
// logLength(123); // โ Error (number doesn't have length)
// 6. Multiple generic types
function pair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
const p1 = pair<string, number>("age", 25);
const p2 = pair("name", "John Kim"); // Type inference
// 7. Generic defaults
interface Container<T = string> {
value: T;
}
const container1: Container = { value: "hello" }; // string
const container2: Container<number> = { value: 123 };
Utility Typesโ
// TypeScript built-in utility types
// 1. Partial<T> (all properties optional)
interface User {
id: number;
name: string;
email: string;
}
function updateUser(id: number, updates: Partial<User>): void {
// updates can have only some properties
}
updateUser(1, { name: "John Kim" }); // OK
updateUser(2, { email: "new@example.com" }); // OK
updateUser(3, { name: "Jane Lee", email: "lee@example.com" }); // OK
// 2. Required<T> (all properties required)
interface PartialUser {
id?: number;
name?: string;
email?: string;
}
type RequiredUser = Required<PartialUser>;
const user: RequiredUser = {
id: 1,
name: "John Kim",
email: "kim@example.com"
// All properties required!
};
// 3. Readonly<T> (all properties readonly)
interface Config {
apiUrl: string;
timeout: number;
}
const config: Readonly<Config> = {
apiUrl: "https://api.example.com",
timeout: 5000
};
// โ Cannot modify
// config.apiUrl = "https://api2.example.com";
// 4. Pick<T, K> (select specific properties)
interface Product {
id: number;
name: string;
price: number;
description: string;
stock: number;
}
type ProductPreview = Pick<Product, "id" | "name" | "price">;
const preview: ProductPreview = {
id: 1,
name: "Laptop",
price: 1000000
// description, stock not needed
};
// 5. Omit<T, K> (exclude specific properties)
type ProductWithoutStock = Omit<Product, "stock">;
const product: ProductWithoutStock = {
id: 1,
name: "Laptop",
price: 1000000,
description: "High-performance laptop"
// stock excluded
};
// 6. Record<K, T> (key-value mapping)
type PageInfo = Record<string, { title: string; url: string }>;
const pages: PageInfo = {
home: { title: "Home", url: "/" },
about: { title: "About", url: "/about" },
contact: { title: "Contact", url: "/contact" }
};
// 7. Exclude<T, U> (exclude type from union)
type AllStatus = "pending" | "approved" | "rejected" | "draft";
type ActiveStatus = Exclude<AllStatus, "draft">;
// "pending" | "approved" | "rejected"
// 8. Extract<T, U> (extract type from union)
type Status = "pending" | "approved" | "rejected";
type PositiveStatus = Extract<Status, "approved">;
// "approved"
// 9. NonNullable<T> (remove null, undefined)
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>;
// string
// 10. ReturnType<T> (extract function return type)
function getUser() {
return {
id: 1,
name: "John Kim",
email: "kim@example.com"
};
}
type User = ReturnType<typeof getUser>;
// { id: number; name: string; email: string }
JavaScript โ TypeScript Conversionโ
// JavaScript code
// user.js
function createUser(name, age, email) {
return {
name: name,
age: age,
email: email,
greet: function() {
return "Hello, " + this.name + "!";
}
};
}
function getUsers() {
return fetch('/api/users')
.then(res => res.json())
.then(data => data.users);
}
const user = createUser("John Kim", 25, "kim@example.com");
console.log(user.greet());
// โ Convert to TypeScript
// user.ts
interface User {
name: string;
age: number;
email: string;
greet(): string;
}
function createUser(name: string, age: number, email: string): User {
return {
name,
age,
email,
greet() {
return `Hello, ${this.name}!`;
}
};
}
interface ApiResponse {
users: User[];
}
async function getUsers(): Promise<User[]> {
const response = await fetch('/api/users');
const data: ApiResponse = await response.json();
return data.users;
}
const user: User = createUser("John Kim", 25, "kim@example.com");
console.log(user.greet());
// Advantages:
// 1. Type safety
// 2. IDE autocomplete
// 3. Easy refactoring
// 4. Prevent bugs in advance
TypeScript in Reactโ
// React component (JavaScript)
// Button.jsx
function Button({ label, onClick, disabled }) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
// โ Convert to TypeScript
// Button.tsx
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
function Button({ label, onClick, disabled = false }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
// Or use React.FC
const Button: React.FC<ButtonProps> = ({ label, onClick, disabled = false }) => {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
};
// Usage
<Button
label="Click"
onClick={() => console.log('clicked')}
disabled={false}
/>
// โ Wrong usage
<Button
label={123} // โ Error: label is string
onClick="handleClick" // โ Error: onClick is function
/>
// 2. State and Hooks
import { useState, useEffect } from 'react';
interface User {
id: number;
name: string;
email: string;
}
function UserProfile() {
// Specify state types
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
setLoading(true);
fetch('/api/user')
.then(res => res.json())
.then((data: User) => {
setUser(data);
setLoading(false);
})
.catch((err: Error) => {
setError(err.message);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!user) return <div>No user</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
// 3. Event Handler
interface FormProps {
onSubmit: (data: { name: string; email: string }) => void;
}
function Form({ onSubmit }: FormProps) {
const [name, setName] = useState<string>('');
const [email, setEmail] = useState<string>('');
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
onSubmit({ name, email });
};
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={handleNameChange}
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
);
}
Common Errors and Solutionsโ
// 1. Object is possibly 'null' or 'undefined'
// โ Error
function getLength(text: string | null) {
return text.length; // โ text might be null
}
// โ
Solution 1: null check
function getLength(text: string | null) {
if (text === null) {
return 0;
}
return text.length; // โ
OK
}
// โ
Solution 2: Optional Chaining
function getLength(text: string | null) {
return text?.length ?? 0;
}
// 2. Type 'X' is not assignable to type 'Y'
// โ Error
interface User {
name: string;
age: number;
}
const user: User = {
name: "John Kim"
// age missing!
};
// โ
Solution: Add all properties
const user: User = {
name: "John Kim",
age: 25
};
// 3. Cannot find name 'X'
// โ Error
console.log(process.env.API_URL); // โ No process type
// โ
Solution: Install @types
// npm install --save-dev @types/node
// 4. Property 'X' does not exist on type 'Y'
// โ Error
const obj = {};
obj.name = "John Kim"; // โ No name property
// โ
Solution 1: Type definition
interface Obj {
name: string;
}
const obj: Obj = { name: "" };
obj.name = "John Kim"; // โ
OK
// โ
Solution 2: Index signature
const obj: { [key: string]: string } = {};
obj.name = "John Kim"; // โ
OK
// 5. Type assertions
const input = document.getElementById('myInput');
// input is HTMLElement | null
// โ Error
input.value = "hello"; // HTMLElement doesn't have value
// โ
Solution: Type assertion
const input = document.getElementById('myInput') as HTMLInputElement;
input.value = "hello"; // โ
OK
// Or
const input = <HTMLInputElement>document.getElementById('myInput');
input.value = "hello"; // โ
OK
// 6. Non-null assertion operator (!)
const element = document.getElementById('app');
// element is HTMLElement | null
// โ Error
element.innerHTML = "hello"; // Might be null
// โ
Solution: null check
if (element) {
element.innerHTML = "hello";
}
// Or ! operator (only when certain!)
element!.innerHTML = "hello"; // Assert not null
// 7. Type narrowing
function printValue(value: string | number) {
// โ Error
// console.log(value.toUpperCase()); // number doesn't have toUpperCase
// โ
Solution: Type check with typeof
if (typeof value === "string") {
console.log(value.toUpperCase()); // โ
OK (string)
} else {
console.log(value.toFixed(2)); // โ
OK (number)
}
}
๐ค Frequently Asked Questionsโ
Q1. Why should we use TypeScript?โ
A: There are several reasons:
// 1. Prevent bugs in advance
// JavaScript
function calculateTotal(items) {
let total = 0;
items.forEach(item => {
total += item.price;
});
return total;
}
// Bugs discovered during execution:
calculateTotal(null); // ๐ฅ Runtime Error!
calculateTotal([{ name: "Product" }]); // ๐ฅ price is undefined
// TypeScript
interface Item {
name: string;
price: number;
}
function calculateTotal(items: Item[]): number {
let total = 0;
items.forEach(item => {
total += item.price;
});
return total;
}
// Discovered during code writing:
calculateTotal(null); // โ Compile Error!
calculateTotal([{ name: "Product" }]); // โ Compile Error! (no price)
// 2. Autocomplete and IntelliSense
const user = {
name: "John Kim",
age: 25,
email: "kim@example.com"
};
// JavaScript: No autocomplete when typing user.
// TypeScript: Autocomplete for name, age, email when typing user.!
// 3. Safe refactoring
// When changing function signature
function greet(name) {
return `Hello, ${name}!`;
}
// TypeScript marks errors at all call sites
// JavaScript only finds problems when executed
// 4. Acts as documentation
// JavaScript
function createUser(name, age, email, isAdmin) {
// Don't know if name is string or number
// Don't know if age is required or optional
// Don't know what isAdmin is
}
// TypeScript
interface CreateUserParams {
name: string;
age: number;
email: string;
isAdmin?: boolean; // Optional, defaults to false
}
function createUser(params: CreateUserParams): User {
// Everything is clear!
}
// 5. Team collaboration
// Looking at TypeScript code:
// - What arguments the function receives
// - What type it returns
// - What properties exist
// Everything is clear!
// Conclusion:
// JavaScript: Fast prototyping, simple scripts
// TypeScript: Large-scale projects, team collaboration, maintenance
Q2. Doesn't TypeScript have any disadvantages?โ
A: There are some disadvantages:
// Disadvantage 1: Learning curve
// Can start immediately knowing only JavaScript
// TypeScript requires learning the type system
// Disadvantage 2: Initial setup
// JavaScript: Create file and run immediately
// TypeScript: Config files, compilation needed
// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
// ... many options
}
}
// Disadvantage 3: Type writing time
// JavaScript
const users = [
{ name: "John Kim", age: 25 },
{ name: "Jane Lee", age: 30 }
];
// TypeScript (type definition needed)
interface User {
name: string;
age: number;
}
const users: User[] = [
{ name: "John Kim", age: 25 },
{ name: "Jane Lee", age: 30 }
];
// Disadvantage 4: Third-party libraries
// Libraries without type definitions require using any
import someLib from 'old-library'; // No types
// Need to install @types/old-library
// Disadvantage 5: Compilation time
// Large projects take compilation time
// (But greatly improved with esbuild, SWC)
// But advantages far outweigh disadvantages!
// Especially essential for large-scale projects!
Q3. Is it okay to use any?โ
A: It's best to avoid it as much as possible:
// โ Overuse of any (loses TypeScript advantages)
function processData(data: any) {
return data.map((item: any) => {
return {
id: item.id,
value: item.value
};
});
}
// โ
Use proper types
interface DataItem {
id: number;
value: string;
}
function processData(data: DataItem[]) {
return data.map(item => {
return {
id: item.id,
value: item.value
};
});
}
// When it's okay to use any:
// 1. Third-party libraries (no type definitions)
import oldLib from 'very-old-library';
const result: any = oldLib.doSomething();
// 2. JSON parsing (unknown structure)
const data: any = JSON.parse(jsonString);
// Then validate with type guards
// 3. Legacy code migration
// Gradual transition from JavaScript โ TypeScript
// Alternatives:
// - unknown: Safer than any
// - Generics: Preserve types
// - Type guards: Runtime validation
Q4. interface vs type, when to use which?โ
A: It depends on the situation:
// Use Interface (recommended)
// 1. Object structure definition
interface User {
id: number;
name: string;
}
// 2. Extensible
interface Student extends User {
studentId: string;
}
// 3. Declaration Merging
interface Window {
myCustomProperty: string;
}
interface Window {
anotherProperty: number;
}
// Both declarations merged!
// Use Type
// 1. Union types
type Status = "pending" | "approved" | "rejected";
// 2. Intersection types
type Employee = Person & Worker;
// 3. Function types
type GreetFunction = (name: string) => string;
// 4. Utility types
type PartialUser = Partial<User>;
type PickedUser = Pick<User, "id" | "name">;
// 5. Tuples
type Point = [number, number];
// 6. Mapped Types
type ReadonlyUser = {
readonly [K in keyof User]: User[K];
};
// Recommendation:
// - Use interface by default
// - Use type when union/intersection needed
// - Maintain consistency (within project)
Q5. How do I start a TypeScript project?โ
A: There are several ways:
# 1. Create React App (TypeScript template)
npx create-react-app my-app --template typescript
# 2. Next.js (TypeScript)
npx create-next-app@latest my-app --typescript
# 3. Vite (TypeScript)
npm create vite@latest my-app -- --template react-ts
# 4. Add TypeScript to existing project
npm install --save-dev typescript @types/react @types/react-dom
# Generate tsconfig.json
npx tsc --init
# 5. Pure TypeScript project
mkdir my-project
cd my-project
npm init -y
npm install --save-dev typescript @types/node
# Generate tsconfig.json
npx tsc --init
# Create src/index.ts file
echo 'console.log("Hello TypeScript!");' > src/index.ts
# Compile
npx tsc
# Execute
node dist/index.js
// tsconfig.json (recommended settings)
{
"compilerOptions": {
// Target JavaScript version
"target": "ES2020",
// Module system
"module": "ESNext",
"moduleResolution": "node",
// JSX support (React)
"jsx": "react-jsx",
// Strict type checking
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
// Module resolution
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
// Output directory
"outDir": "./dist",
// Source map generation
"sourceMap": true,
// Skip unnecessary checks
"skipLibCheck": true,
// Path aliases
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
๐ Next Stepsโ
Once you understand TypeScript basics, try learning:
- What is React? (document in progress) - React development with TypeScript
- What is a Bundler? - TypeScript build environment
- What is TDD? (document in progress) - Writing tests with TypeScript
๐ฌ Conclusionโ
TypeScript makes JavaScript safer and more productive:
- Type Safety: Prevent bugs in advance
- Autocomplete: Improve development speed
- Refactoring: Safe code changes
- Documentation: Code as documentation
TypeScript is essential for large-scale projects and team collaboration. There's a learning curve, but it's well worth the investment!