Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

TypeScript Fundamentals: From Basic Types to Advanced Patterns

Tech 1

Basic Types

TypeScript adds static typing to JavaScript, making code more maintainable and catching errors at compile time rather than runtime.

'use strict'

let username: string = "hello"
let count: number = 42
let isActive: boolean = false
let empty: null = null
let pending: undefined = undefined
let optionalValue: string | null = null

// Type assertion for narrowing
let numbers = [10, 20, 30]
const result = numbers.find(item => item > 15) as number
console.log(result * 2)

Complex Types

Arrays

let numericList: number[] = [1, 2, 3]
let stringList: Array<string> = ['x', 'y', 'z']

Tuples

Tuples allow defining arrays with fixed types at specific positions.

let record: [number, string, boolean] = [1, 'data', true]
let partial: [number, string, number?] = [1, 'data'] // last element optional

Enums

enum Direction {
  Up,
  Down,
  Left,
  Right
}

console.log(Direction.Up)    // 0
console.log(Direction[0])    // 'Up'

Functions

function processData(
  id: number,
  label: string,
  enabled?: boolean,      // optional parameter
  ...tags: number[]      // rest parameters
): void {
  console.log(id, label)
}

processData(100, 'test', true, 1, 2, 3)

Interfaces

interface UserProfile {
  username: string
  age: number
}

const user1: UserProfile = {
  username: 'alice',
  age: 25
}

const user2: UserProfile = {
  username: 'bob',
  age: 30
}

Type Aliases

For reducing repetition with union types.

type UserId = string | number
let id1: UserId = 'user-001'
let id2: UserId = 1001

Generics

Generics provide type safety for functions that work with multiple types.

function combine<T>(first: T, second: T): T[] {
  return [first, second]
}

combine<number>(1, 2)        // valid
combine<string>('a', 'b')    // valid
combine<number | string>(1, 'a') // valid
combine<number>(1, 'a')      // error: type mismatch

Advanced Concepts

Interface Inheritance

interface Vehicle {
  wheels: number
  speed: number
}

interface Car extends Vehicle {
  brand: string
}

const myCar: Car = {
  wheels: 4,
  speed: 120,
  brand: 'Tesla'
}

Classes

class Article {
  title: string
  body: string
  category?: string     // optional property
  views = 0             // default value
  private draft?: string
  protected metadata?: object
  static readonly publisher: string = 'TechPress'

  constructor(title: string, body: string) {
    this.title = title
    this.body = body
  }
}

class BlogPost extends Article {
  constructor(title: string, body: string) {
    super(title, body)
    this.metadata  // accessible: protected allows subclass access
  }
}

const post = new Article('Intro', 'Content here')
// post.draft       // error: private, only accessible within Article
// post.metadata    // error: protected, only accessible within Article or subclasses
// Article.publisher // static: accessed via class, not instance

Accessors

class Account {
  private _token: string = ''

  get token(): string {
    return '********'
  }

  set token(newToken: string) {
    this._token = newToken
  }
}

const account = new Account()
account.token = 'abc123'
console.log(account.token) // displays: ********

Abstract Classes

Abstract classes define contracts without direct instantiation.

abstract class Shape {
  abstract color: string
  abstract calculateArea(): number

  display(): void {
    console.log('Rendering shape')
  }
}

class Circle extends Shape {
  color: string = 'blue'
  radius: number = 5

  calculateArea(): number {
    return Math.PI * this.radius ** 2
  }
}

Implementing Interfaces

Unlike inheritance, a class can implement multpile interfaces.

interface Named {
  name: string
}

interface Describable {
  describe(): string
}

interface Aged {
  years: number
}

class Person implements Named, Aged {
  name: string = 'John'
  years: number = 28

  describe(): string {
    return `${this.name} is ${this.years} years old`
  }
}

Gneerics in Classes

class Container<T> {
  private data: T

  constructor(initial: T) {
    this.data = initial
  }

  transform(input: T): T {
    console.log('Processing:', this.data)
    return input
  }
}

const textContainer = new Container<string>('world')
textContainer.transform('hello')

const numContainer = new Container<number>(999)
numContainer.transform(100)

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.