Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kirilkirkov/b6ffc64776fe7af0b99ee69dcabce7bc to your computer and use it in GitHub Desktop.
Save kirilkirkov/b6ffc64776fe7af0b99ee69dcabce7bc to your computer and use it in GitHub Desktop.
TypeScript Best Practices

How public and private class access modifiers are compiled to javascript in typescript

public: The public access modifier in TypeScript does not result in any changes during compilation. This is because in JavaScript, all class members are by default considered public. Therefore, a public member in a TypeScript class remains unchanged in the resulting JavaScript code.

// Example TypeScript code:
class MyClass {
  public publicProperty: string;
  
  public publicMethod(): void {
    // Method implementation
  }
}
// Equivalent JavaScript code after compilation:
class MyClass {
  constructor() {
    // Constructor implementation
  }
  
  publicMethod() {
    // Method implementation
  }
}

private: The private access modifier in TypeScript is compiled to JavaScript using a technique called "name mangling." This technique involves transforming the private member names by adding a prefix to make them harder to access from outside the class.

// Example TypeScript code:
class MyClass {
  private privateProperty: string;
  
  private privateMethod(): void {
    // Method implementation
  }
}
// Equivalent JavaScript code after compilation:
class MyClass {
  constructor() {
    // Constructor implementation
    this._privateProperty = '';
  }
  
  _privateMethod() {
    // Method implementation
  }
}

In the compiled JavaScript code, the privateProperty is renamed to _privateProperty, and the privateMethod is renamed to _privateMethod. Although these names are not truly private, they serve as a convention to indicate that they are intended for internal use within the class and should not be accessed directly from outside.

It's important to note that the encapsulation provided by private in TypeScript is enforced during compile-time, but it doesn't prevent access to private members at runtime. JavaScript's nature allows bypassing private access restrictions. However, adhering to the naming conventions and documentation helps developers understand the intended usage and discourages accessing private members directly.

Tuples

// define our tuple
let ourTuple: [number, boolean, string];

// initialize correctly
ourTuple = [5, false, 'Coding God was here'];

A good practice is to make your tuple readonly.

unknown vs any in TypeScript

// Example of any
let myVar: any = 0;
myVar = '1';
myVar = false;
// Example of unknown
let myVar: unknown = 0;
myVar = '1';
myVar = false;

To better understand the difference between unknown and any, let's start with writing a function that wants to invoke its only argument.

function invokeAnything(callback: any) {
  callback();
}

invokeAnything(1);

But running the script throws a runtime error: TypeError: callback is not a function. 1 is a number and cannot be invoked as a function — and TypeScript hasn't protected you from this error! So we will not get Errors during the development!

function invokeAnything(callback: unknown) {
  callback(); // Type error: 'callback' is of type 'unknown'
}

invokeAnything(1);

But if we use unknown we will get the error!

  • You can assign anything to unknown type but you have to do a type check or type assertion to operate on unknown
  • You can assign anything to any type and you can perform any operation on any

unknown is recommended over any because it provides safer typing — you have to use type assertion or narrow to a specific type if you want to perform operations on unknown.

Describe your data

type Result = "success" | "failure"
function verifyResult(result: Result) {
    if (result === "success") {
        console.log("Passed");
    } else {
        console.log("Failed")
    }
}

Use enums

enum EventType {
    Create,
    Delete,
    Update
}

class InfraEvent {
    constructor(event: EventType) {
        if (event === EventType.Create) {
            // Call for other function
            console.log(`Event Captured :${event}`);
        }
    }
}

let eventSource: EventType = EventType.Create;
const eventExample = new InfraEvent(eventSource)
@kirilkirkov
Copy link
Author

Good explain of "unknown vs any" in TypeScript - https://dmitripavlutin.com/typescript-unknown-vs-any/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment