Ensiklopedia VibeKoding: Principles of TypeScript.Ensiklopedia VibeKoding: Principles of TypeScript.
You already know JavaScript, but you may have encountered these problems: - Assigning the wrong type to a variable, only discovering it at runtime - Misspelling an object property name and spending ages debugging - Function parameter types being wrong, leading to constant rewrites TypeScript is the tool that helps you catch these issues before your code runs. After reading this, you'll understand why TypeScript improves code quality, how to read type annotations, interfaces, generics, and other core concepts, and how to better leverage AI-generated code in vibecoding.You already know JavaScript, but you may have encountered these problems: - Assigning the wrong type to a variable, only discovering it at runtime - Misspelling an object property name and spending ages debugging - Function parameter types being wrong, leading to constant rewrites TypeScript is the tool that helps you catch these issues before your code runs. After reading this, you'll understand why TypeScript improves code quality, how to read type annotations, interfaces, generics, and other core concepts, and how to better leverage AI-generated code in vibecoding.
What will this article teach you?What will this article teach you?
| Chapter | Content | What you'll be able to do |
|---|---|---|
| Chapter 1 | What TypeScript is | Understand its relationship with JavaScript |
| Chapter 2 | Basic type annotations | Know how to annotate types for variables |
| Chapter 3 | Object types and interfaces | Define types for data structures |
| Chapter 4 | Function types | Annotate types for function parameters and return values |
| Chapter 5 | Generics | Write reusable, type-safe code |
| Chapter 6 | Type inference and practical tips | Know when explicit annotations are needed |
------
JavaScript already works โ why do we need TypeScript? Is learning an extra syntax worth it?JavaScript already works โ why do we need TypeScript? Is learning an extra syntax worth it?
๐ด JavaScript's Pain Points๐ด JavaScript's Pain Points Like a document editor without spell checkLike a document editor without spell check โ
TypeScript's Advantagesโ
TypeScript's Advantages Like an editor with spell check and syntax highlightingLike an editor with spell check and syntax highlighting
Understand their relationship in one sentence:Understand their relationship in one sentence:
| Technology | Analogy | Role |
|---|---|---|
| JavaScript | Raw material | Code that can run directly |
| TypeScript | Blueprint + quality check | Adds type checking to JavaScript, then compiles to JavaScript |
A developer used AI to generate a user management feature. The AI-written JavaScript code ran, but there was a problem: the user's age was supposed to be a number, but sometimes it was mistakenly assigned as a string. As a result, when checking "is the user an adult," the string "25" was treated as a string, causing the check to fail. This bug was hidden for a long time until a user entered a non-numeric character and it surfaced. With TypeScript, this code would have errored at write time: Type 'string' is not assignable to type 'number'. This is the value of TypeScript โ when AI gets a type wrong, you can catch it immediately.A developer used AI to generate a user management feature. The AI-written JavaScript code ran, but there was a problem: the user's age was supposed to be a number, but sometimes it was mistakenly assigned as a string. As a result, when checking "is the user an adult," the string "25" was treated as a string, causing the check to fail. This bug was hidden for a long time until a user entered a non-numeric character and it surfaced. With TypeScript, this code would have errored at write time: Type 'string' is not assignable to type 'number'. This is the value of TypeScript โ when AI gets a type wrong, you can catch it immediately.
TypeScript is not a brand-new language; it's simply a "superset" of JavaScript:TypeScript is not a brand-new language; it's simply a "superset" of JavaScript:
typescript // This is valid JavaScript, and also valid TypeScript const name = "Zhang San" const age = 25 function greet(user) { return `Hello ${user}` } // This is TypeScript-specific type annotation const name2: string = "Li Si" const age2: number = 30 function greet2(user: string): string { return `Hello ${user}` }
Key takeaways:Key takeaways:
TypeScript doesn't change how your code runs; it just checks that types are correct at compile time. You can adopt TypeScript incrementally โ start by adding types to critical variables.TypeScript doesn't change how your code runs; it just checks that types are correct at compile time. You can adopt TypeScript incrementally โ start by adding types to critical variables.
------
How do you tell TypeScript what type a variable should be? What is the syntax for type annotations?How do you tell TypeScript what type a variable should be? What is the syntax for type annotations?
A type annotation is simply adding : type after the variable name:A type annotation is simply adding : type after the variable name:
typescript // Syntax: variableName: type = value const name: string = "Zhang San" let age: number = 25 let isStudent: boolean = true
๐ Try it yourself: Add type annotations to variables๐ Try it yourself: Add type annotations to variables
TypeScript can automatically infer types based on assignment: ``typescript // These don't need type annotations โ TypeScript can infer them const name = "Zhang San" // inferred as string const age = 25 // inferred as number const isActive = true // inferred as boolean // These cases need explicit annotations let data // โ Error: cannot infer type let data: any // โ
Works, but loses the benefit of type checking function add(a, b) { // โ Parameter types are unclear return a + b } function add2(a: number, b: number): number { // โ
Types are explicit return a + b } ``TypeScript can automatically infer types based on assignment: ``typescript // These don't need type annotations โ TypeScript can infer them const name = "Zhang San" // inferred as string const age = 25 // inferred as number const isActive = true // inferred as boolean // These cases need explicit annotations let data // โ Error: cannot infer type let data: any // โ
Works, but loses the benefit of type checking function add(a, b) { // โ Parameter types are unclear return a + b } function add2(a: number, b: number): number { // โ
Types are explicit return a + b } ``
TypeScript supports all of JavaScript's basic types:TypeScript supports all of JavaScript's basic types:
| Type | Description | Example |
|---|---|---|
string | String | "hello", 'ไฝ ๅฅฝ' |
number | Number (integers and decimals) | 42, 3.14 |
boolean | Boolean | true, false |
null / undefined | Null value | null, undefined |
array | Array | number[], string[] |
object | Object | { name: string; age: number } |
Two ways to write array types:Two ways to write array types:
typescript // Method 1: type[] (more common) const numbers: number[] = [1, 2, 3, 4, 5] const names: string[] = ["Zhang San", "Li Si", "Wang Wu"] // Method 2: Array<type> const numbers2: Array<number> = [1, 2, 3, 4, 5] const names2: Array<string> = ["Zhang San", "Li Si", "Wang Wu"]
Special types:Special types:
typescript // any: any type (use sparingly โ effectively disables type checking) let data: any = 42 data = "now it can be a string" data = { name: "Zhang San" } // can also be an object // unknown: type-safe any let value: unknown = 42 // if (typeof value === "number") { // console.log(value + 10) // must check type first before using // } // void: no return value function log(message: string): void { console.log(message) } // never: never returns function error(message: string): never { throw new Error(message) }
- See : string โ this is a string type annotation - See : number[] โ this is a number array annotation - See : void โ this function has no return value- See : string โ this is a string type annotation - See : number[] โ this is a number array annotation - See : void โ this function has no return value
------
How do you define the type of an object? What types should the object's properties be?How do you define the type of an object? What types should the object's properties be?
Interfaces are the primary way to define object types in TypeScript:Interfaces are the primary way to define object types in TypeScript:
typescript // Define a User interface interface User { id: number name: string email: string age?: number // optional property } // Use the interface const user: User = { id: 1, name: "Zhang San", email: "zhangsan@example.com", age: 25 } // age is optional, so it can be omitted const user2: User = { id: 2, name: "Li Si", email: "lisi@example.com" }
๐ Try it yourself: Create objects that conform to an interface definition๐ Try it yourself: Create objects that conform to an interface definition
``typescript // Readonly properties interface User { readonly id: number // id cannot be modified after creation name: string } const user: User = { id: 1, name: "Zhang San" } user.id = 2 // โ Error: cannot modify a readonly property user.name = "Li Si" // โ
Can modify // Function types interface User { name: string greet: () => string // greet is a function that returns string } const user: User = { name: "Zhang San", greet: () => "Hello" } // Interface inheritance interface Admin extends User { permissions: string[] } const admin: Admin = { name: "Admin", greet: () => "Hello Admin", permissions: ["read", "write", "delete"] } ````typescript // Readonly properties interface User { readonly id: number // id cannot be modified after creation name: string } const user: User = { id: 1, name: "Zhang San" } user.id = 2 // โ Error: cannot modify a readonly property user.name = "Li Si" // โ
Can modify // Function types interface User { name: string greet: () => string // greet is a function that returns string } const user: User = { name: "Zhang San", greet: () => "Hello" } // Interface inheritance interface Admin extends User { permissions: string[] } const admin: Admin = { name: "Admin", greet: () => "Hello Admin", permissions: ["read", "write", "delete"] } ``
Besides interfaces, you can also use type to define type aliases:Besides interfaces, you can also use type to define type aliases:
typescript // Type alias type User = { id: number name: string email: string } // Union types type Status = "pending" | "success" | "error" const status: Status = "success" // โ
// const status2: Status = "failed" // โ Error: not in the union type // Intersection types (merge multiple types) type User = { id: number name: string } type Timestamp = { createdAt: Date updatedAt: Date } type UserWithTimestamp = User & Timestamp const user: UserWithTimestamp = { id: 1, name: "Zhang San", createdAt: new Date(), updatedAt: new Date() }
Interface vs Type Alias:Interface vs Type Alias:
| Feature | interface | type |
|---|---|---|
| Extension | extends | & intersection |
| Duplicate declaration | Auto-merges | Errors |
| Use cases | Object shapes, classes | Union types, intersection types, primitive type aliases |
- See interface โ defining an object type - See type โ creating a type alias - See ? โ optional property - See readonly โ readonly property- See interface โ defining an object type - See type โ creating a type alias - See ? โ optional property - See readonly โ readonly property
------
How do you annotate types for function parameters and return values?How do you annotate types for function parameters and return values?
typescript // Complete function type annotation function add(a: number, b: number): number { return a + b } // Arrow function const multiply = (a: number, b: number): number => { return a * b } // No return value function log(message: string): void { console.log(message) } // Returning multiple types (union type) function parseInput(input: string): number | string { const num = parseFloat(input) return isNaN(num) ? input : num }
typescript // Optional parameter (marked with ?) function greet(name: string, title?: string): string { return title ? `${title} ${name}` : name } greet("Zhang San") // "Zhang San" greet("Zhang San", "Mr.") // "Mr. Zhang San" // Default parameter function greet2(name: string, title: string = "friend"): string { return `${title} ${name}` } greet2("Li Si") // "friend Li Si" greet2("Li Si", "Dr.") // "Dr. Li Si"
typescript // Accepting a function as a parameter function calculate( a: number, b: number, operation: (x: number, y: number) => number ): number { return operation(a, b) } calculate(10, 5, (x, y) => x + y) // 15 calculate(10, 5, (x, y) => x * y) // 50 // Cleaner approach: define the function type first type Operation = (x: number, y: number) => number function calculate2( a: number, b: number, operation: Operation ): number { return operation(a, b) }
- See (a: number, b: number) => number โ this is a function type, describing parameters and return value - See : void โ the function has no return value - See ? โ the parameter is optional- See (a: number, b: number) => number โ this is a function type, describing parameters and return value - See : void โ the function has no return value - See ? โ the parameter is optional
------
How do you write code that handles multiple types while staying type-safe?How do you write code that handles multiple types while staying type-safe?
Generics let you define functions, interfaces, or classes without specifying concrete types upfront โ you specify them at usage time:Generics let you define functions, interfaces, or classes without specifying concrete types upfront โ you specify them at usage time:
typescript // Generic function: T is a type variable function identity<T>(arg: T): T { return arg } // Explicitly specify the type at usage const num1 = identity<number>(42) // type is number const str1 = identity<string>("hello") // type is string // Type inference: TypeScript can infer automatically const num2 = identity(42) // inferred as number const str2 = identity("hello") // inferred as string
๐ Try it yourself: Use generics to handle different types of data๐ Try it yourself: Use generics to handle different types of data
Restrict generics to meet certain conditions:Restrict generics to meet certain conditions:
typescript // Constrain T to have a length property interface HasLength { length: number } function logLength<T extends HasLength>(arg: T): void { console.log(arg.length) } logLength("hello") // โ
strings have length logLength([1, 2, 3]) // โ
arrays have length // logLength(42) // โ numbers don't have a length property
typescript // Generic interface interface Box<T> { value: T getValue(): T } const numberBox: Box<number> = { value: 42, getValue: () => 42 } const stringBox: Box<string> = { value: "hello", getValue: () => "hello" } // Generic class class Storage<T> { private items: T[] = [] add(item: T): void { this.items.push(item) } get(index: number): T { return this.items[index] } } const numberStorage = new Storage<number>() numberStorage.add(1) numberStorage.add(2) // numberStorage.add("string") // โ Error const stringStorage = new Storage<string>() stringStorage.add("hello") // stringStorage.add(1) // โ Error
- See โ this is a generic type variable - See โ generic constraint - See Array or Promise โ built-in generic types- See โ this is a generic type variable - See โ generic constraint - See Array or Promise โ built-in generic types
------
When do you need explicit type annotations? When can you rely on inference?When do you need explicit type annotations? When can you rely on inference?
TypeScript can automatically infer types from context:TypeScript can automatically infer types from context:
typescript // Inference during variable initialization const name = "Zhang San" // inferred as string const age = 25 // inferred as number const isActive = true // inferred as boolean // Array inference const numbers = [1, 2, 3] // inferred as number[] const mixed = [1, "hello", true] // inferred as (number | string | boolean)[] // Function return value inference function add(a: number, b: number) { return a + b // return value inferred as number }
๐ Try it yourself: Observe how TypeScript infers types๐ Try it yourself: Observe how TypeScript infers types
``typescript // โ
Recommended: simple literal assignments const count = 0 const name = "Zhang San" const isActive = true // โ
Recommended: function return values that can be inferred function getUserId(user: User) { return user.id // inferred as number } ````typescript // โ
Recommended: simple literal assignments const count = 0 const name = "Zhang San" const isActive = true // โ
Recommended: function return values that can be inferred function getUserId(user: User) { return user.id // inferred as number } ``
``typescript // โ
Recommended: function parameters (required) function add(a: number, b: number) { return a + b } // โ
Recommended: object property types are unclear const user: { id: number name: string metadata: Record````typescript // โ
Recommended: function parameters (required) function add(a: number, b: number) { return a + b } // โ
Recommended: object property types are unclear const user: { id: number name: string metadata: Record``
Check types at runtime:Check types at runtime:
typescript // typeof type guard function processValue(value: string | number) { if (typeof value === "string") { // TypeScript knows value is string here console.log(value.toUpperCase()) } else { // TypeScript knows value is number here console.log(value * 2) } } // instanceof type guard class Dog { bark() { console.log("Woof") } } class Cat { meow() { console.log("Meow") } } function makeSound(animal: Dog | Cat) { if (animal instanceof Dog) { animal.bark() // TypeScript knows this is Dog } else { animal.meow() // TypeScript knows this is Cat } } // Custom type guard interface User { name: string email: string } function isUser(value: any): value is User { return ( typeof value === "object" && value !== null && typeof value.name === "string" && typeof value.email === "string" ) } function processValue(value: unknown) { if (isUser(value)) { // value is User here console.log(value.name) } }
TypeScript provides some built-in utility types:TypeScript provides some built-in utility types:
typescript // Partial: make all properties optional interface User { id: number name: string email: string } type PartialUser = Partial<User> // Equivalent to: { id?: number; name?: string; email?: string } // Required: make all properties required type RequiredUser = Required<PartialUser> // Equivalent to: { id: number; name: string; email: string } // Pick: keep only specified properties type UserBasicInfo = Pick<User, "id" | "name"> // Equivalent to: { id: number; name: string } // Omit: exclude specified properties type UserWithoutEmail = Omit<User, "email"> // Equivalent to: { id: number; name: string } // Record: create an object type type UserRoles = Record<string, boolean> // Equivalent to: { [key: string]: boolean }
------
How can you better leverage TypeScript in AI-assisted development?How can you better leverage TypeScript in AI-assisted development?
โ Bad prompt:โ Bad prompt:
CODE Write a user management feature for me
โ Good prompt:โ Good prompt:
CODE Write a user management feature for me, using TypeScript. The data structure is defined as follows: interface User { id: number name: string email: string age: number } I need to implement: 1. Get user list: returns User[] 2. Create user: accepts Partial<User>, returns User 3. Update user: accepts id and Partial<User>, returns User 4. Delete user: accepts id, returns void Please ensure all functions have complete type annotations.
Common errors and their meanings:Common errors and their meanings:
| Error Message | Meaning | Solution |
|---|---|---|
Type 'X' is not assignable to type 'Y' | Type X cannot be assigned to type Y | Check if types match, or perform type conversion |
Property 'X' does not exist on type 'Y' | Property X does not exist on type Y | Check property name spelling, or define the property |
Argument of type 'X' is not assignable to parameter of type 'Y' | Parameter type mismatch | Check the argument types when calling the function |
Type 'X' is missing the following properties from type 'Y' | Type X is missing certain properties from type Y | Add the missing properties |
If you have a JavaScript project, you can gradually migrate to TypeScript:If you have a JavaScript project, you can gradually migrate to TypeScript:
.tsStep 1: Rename files to .tsbash # From utils.js to utils.ts mv utils.js utils.ts
typescript // If you get: Parameter 'a' implicitly has an 'any' type // Add type annotations function add(a: number, b: number) { return a + b }
typescript // First use any for a quick fix function processUser(user: any) { // ... } // Later refine the types interface User { id: number name: string } function processUser(user: User) { // ... }
json // tsconfig.json { "compilerOptions": { "strict": true, // Enable strict mode "noImplicitAny": true, // Disallow implicit any "strictNullChecks": true // Strict null checks } }
------
: string โ this is a string type annotationSee : string โ this is a string type annotation: number[] โ this is a number array annotationSee : number[] โ this is a number array annotationinterface User โ this defines an object typeSee interface User โ this defines an object typetype User = โ this is a type aliasSee type User = โ this is a type alias โ this is a genericSee โ this is a genericextends โ interface inheritance or generic constraintSee extends โ interface inheritance or generic constraint? โ optional propertySee ? โ optional propertyreadonly โ readonly propertySee readonly โ readonly property| โ union typeSee | โ union type& โ intersection typeSee & โ intersection typeIf you read the "deep dive" section of each chapter carefully, you've also mastered these core concepts:If you read the "deep dive" section of each chapter carefully, you've also mastered these core concepts:
- "How should I write the type annotation for this function? The parameter is X, the return value is Y" - "Help me define an interface that describes this data structure: ..." - "What does this TypeScript error mean? How do I fix it?" - "How do I add a constraint to this generic function to ensure T must have a certain property?"- "How should I write the type annotation for this function? The parameter is X, the return value is Y" - "Help me define an interface that describes this data structure: ..." - "What does this TypeScript error mean? How do I fix it?" - "How do I add a constraint to this generic function to ensure T must have a certain property?"