Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Overview of TypeScript Type System and Core Features

Tech 1

1. Common Type Annotations

Basic type annotation syntax example:

let userAge: number = 24;

Existing Types Inherited from JavaScript

  • Primitive types: number, string, boolean, null, undefined, symbol
  • Object types: object (includes arrays, plain objects, functions and other object values)

New Types Introduced by TypeScript

Union types, type aliases, interfaces, tuples, literal types, enums, void, any and more.

Key Difference Between Type Alias and Interface

  • Type aliases can define constraints for any data type
  • Interfaces can only define constraints for object types

Common type usage examples:

// Two ways to write array types
let testScores: number[] = [92, 85, 77, 98]; // Recommended approach
let fruitList: Array<string> = ['apple', 'banana', 'orange', 'grape'];

// Union type usage
let userId: number | string = 'user_8a7d6f';
let entryValue: number | string[] = 404; // Either a number or a string array
let mixedCollection: (number | string)[] = [200, 'request success', 404, 'not found']; // Array with both number and string values

// Type alias
type MixedNumStrArray = (number | string)[];
let orderRecords: MixedNumStrArray = [1001, 'wireless headphone', 1002, 'bluetooth speaker'];

// Function type annotation
function calculateDouble(input: number): number {
    return input * 2;
}
// Optional function parameter, void return type
function printLog(message?: string): void {
    console.log(message || 'No log content provided');
}

// Object type annotation
let customer: {
    fullName: string;
    age: number;
    sendGreeting(): void
} = {
    fullName: 'Luna Garcia',
    age: 28,
    sendGreeting() {}
};

// Interface definition
interface PlatformUser {
    username: string;
    age: number;
}
let registeredUser: PlatformUser = { username: 'luna01', age: 28 };

// Interface inheritance
interface Point2D { x: number; y: number }
interface Point3D extends Point2D { z: number }

// Tuple type
let geoCoordinates: [number, number] = [39.9042, 116.4074];

// Type inference
let postCount = 10; // Automatically inferred as number type
let unassignedVar; // No inferred type, defaults to any
unassignedVar = 5;

// Literal type
const adminRole = "super_admin"; // Const-declared constant has literal type "super_admin"
let allowedRole: "admin" | "editor" | "viewer" = "editor"; // Only allows 3 specified string values

// Enumeration (enum) type
enum UserRole { SuperAdmin, Editor, Viewer }
let currentUserRole: UserRole = UserRole.Editor;
// Default numeric enum increments from 0, output: 0 1 2
console.log(UserRole.SuperAdmin, UserRole.Editor, UserRole.Viewer);
// Custom starting value for numeric enum
enum StatusCode { Ok = 200, Created, BadRequest = 400, NotFound }
// StatusCode.Ok=200, StatusCode.Created=201, StatusCode.NotFound=401
// String enum requires explicit initial value for all members
enum NotificationType { Success = "SUCCESS", Error = "ERROR", Warning = "WARNING" }

// any type (bypasses all type checks)
let arbitraryValue: any = { count: 0 };
arbitraryValue(); // No type error
arbitraryValue.nonExistentProperty = 10; // No type error

// typeof operator in TypeScript
let referencePoint = { x: 15, y: 25 };
// Equivalent to (point: { x: number; y: number }) => void
function drawPoint(point: typeof referencePoint) {
    // Drawing logic
}

2. Advanced Type Annotations

Advanced type features include:

  • Class type system
  • Type compatibility
  • Intersection types
  • Generics and keyof operator
  • Endex signature types, index query types
  • Mapping types

2.1 Class Type

Basic class usage example:

class Product {
    basePrice = 99;
}
const laptop = new Product();
// laptop is inferred as Product type, laptop.basePrice is number type
console.log(laptop.basePrice);

Class with constructor and instance methods:

class Product {
    basePrice: number;
    category: string;

    constructor(basePrice: number, category: string) {
        this.basePrice = basePrice;
        this.category = category;
    }

    adjustPrice(increment: number): void {
        this.basePrice += increment;
    }
}

const smartphone = new Product(699, 'electronics');
smartphone.adjustPrice(50);
// smartphone.basePrice becomes 749

2.2 Class Inheritance and Interface Implementation

Class Inheritance (extends keyword)

class Creature {
    move(): void {
        console.log('Moving along the path');
    }
}

class Cat extends Creature {
    meow(): void {
        console.log('Meow~');
    }
}

const strayCat = new Cat();
strayCat.move(); // Inherited from parent class
strayCat.meow(); // Own method

Interface Implementation (implements keyword)

// Step 1: Define interface constraint
interface Playable {
    play(): void;
}

// Step 2: Class implements interface, must implement all methods defined in interface
class MusicTrack implements Playable {
    play(): void {
        console.log('Playing audio track');
    }
}

2.3 Access Modifiers: public / protected / private

  • public: Accessible anywhere (default modifier)
  • protected: Accessible only inside the class and its subclasses, not accessible from class instances
  • private: Accesisble only inside the class itself

2.4 readonly Modifier

class Employee {
    // Explicit type annotation is required, otherwise type will be inferred as literal 1000
    readonly employeeId: number = 1000;
    constructor(employeeId: number) {
        // Can modify readonly property only inside constructor
        this.employeeId = employeeId;
    }
}

const staffMember = new Employee(1024);
console.log(staffMember.employeeId); // Allowed to read
staffMember.employeeId = 2048; // Type error, cannot modify readonly property outside constructor

2.5 Type Compatibility

[Note: Original type compatibility comparison diagrams are not available, this section is omitted for clarity.]


2.6 Intersection Types

Combine multiple type constraints into one:

interface Customer { fullName: string }
interface ContactInfo { phoneNumber: string }
// CustomerProfile has all properties from both Customer and ContactInfo
type CustomerProfile = Customer & ContactInfo;

2.7 Generics

Generic Function

// <Type> is a generic type placeholder
function identity<Type>(inputValue: Type): Type {
    return inputValue;
}

// Explicitly specify generic type
const numberResult = identity<number>(123);
// Generic type can be omitted thanks to type inference
const stringResult = identity('test string content');

Generic Constraints

// Constraint that input must be an array of generic type
function getArrayLength<Type>(inputArray: Type[]): number {
    return inputArray.length;
}

// Use extends to add custom generic constraint
interface LengthAvailable { length: number }
function logInputLength<Type extends LengthAvailable>(input: Type): void {
    // Input is guaranteed to have length property, no type error
    console.log(input.length);
}

keyof Operator

// Constraint that key must be a valid property of the input object
function getProperty<ObjType, Key extends keyof ObjType>(obj: ObjType, key: Key) {
    return obj[key];
}

getProperty({ bookTitle: 'TypeScript Guide', pageCount: 320 }, 'bookTitle');
getProperty({ bookTitle: 'TypeScript Guide', pageCount: 320 }, 'pageCount');

Ganeric Interface

interface CrudService<DataType> {
    getById: (id: number) => DataType;
    getAll: () => DataType[];
}

// Implement generic interface with specified type
const userService: CrudService<PlatformUser> = {
    getById(id) {
        return { username: 'test_user', age: 26 };
    },
    getAll() {
        return [];
    }
};

2.8 Generic Utility Types

Common built-in generic utility types:

  • Partial<Type>: Make all properties of Type optional
  • Readonly<Type>: Make all properties of Type read-only
  • Pick<Type, Keys>: Select specified Keys from Type to construct a new type
  • Record<Keys, Type>: Construct a object type with key type Keys and value type Type

[Note: Orgiinal utility type usage diagrams are not available, detailed examples are omitted.]

Tags: typescript

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.