The Drama Surrounding TypeScript’s Removal in Turbo 8 by DHH

In the fast-paced world of software development, even the most respected figures can spark cowntroversy. This time, it’s David Heinemeier Hansson, better known as DHH, a Danish-American software engineer famous for creating the Ruby on Rails web framework. The latest uproar comes from his announcement that Turbo 8, a toolchain for frontend development, will be dropping TypeScript in its next release.

In a blog post, DHH candidly expressed his preference for JavaScript’s simplicity and flexibility. While he acknowledged TypeScript’s merits and its thriving community, he argued that it complicates development without providing sufficient benefits for their project.

However, this decision wasn’t without its critics. Many developers pushed back against DHH’s move, leading to a heated debate (see this).

I think what sets this situation apart is DHH’s unapologetic stance. Despite the pushback, he disregarded all the comments and merged the pull request, raising eyebrows across the tech community.

The decision triggered a wave of responses from tech influencers. Some were against DHH’s move, while others supported it. One individual, Theo, even created a pull request to reintegrate TypeScript into the repository, receiving a positive response and engaging in a back-and-forth with DHH.

The Core Issue

Is DHH’s decision justified? It’s essential to separate DHH’s reputation for being somehow arrogant and dismissive when facing criticism from the real issue at hand: the removal of TypeScript.

TypeScript, often considered “meh” by some, offers static typing and is great for onboarding new developers. However, as DHH noted, it can lead to code bloat without adding significant value. He also praised the compatibility between JavaScript and TypeScript, allowing developers to choose between the two.

The question remains: why remove TypeScript and deprecate type libraries maintained by the Turbo project?

It is about User-Friendly vs. User-Hostile

While there is nothing inherently wrong with moving away from TypeScript, the removal might be seen as user-hostile. It could create difficulties for less-experienced users who rely on TypeScript’s safety net.

In the end, it’s a complex issue with valid arguments on both sides. Developers like DHH, who drive both race cars and software innovation, make bold decisions. Perhaps, this drama serves as a reminder for all of us to be adaptable developers who don’t go on Twitter rants when faced with tools we don’t particularly like.

In the ever-evolving world of software development, opinions will clash, and changes will happen. As for Turbo 8 and TypeScript, only time will tell how this controversy plays out in the world of coding. Meanwhile, I guess, different strokes for different folks. 🙂

Read more:

Share
The Drama Surrounding TypeScript’s Removal in Turbo 8 by DHH

Bun in Fun

Recently, Bun 1.0 was released, offering exciting new possibilities for JavaScript developers.

About Bun

At its core, Bun is a drop-in replacement for Node.js that focuses on backward compatibility while significantly improving performance. It’s designed to handle JavaScript and TypeScript (TSX) files seamlessly, all without the need for additional dependencies. The creator of Bun highlights its ability to replace traditional npm run commands, making the development experience smoother and faster.

But, why choose Bun?

  1. Improved Performance:
    Bun leverages JavaScript Core, the same engine used by Safari, which offers faster boot-up and runtime speeds compared to V8 (used by Chrome). Benchmarks indicate that Bun can handle more requests per second, a crucial advantage when dealing with high-demand applications.
  2. Simplified Imports:
    Bun abstracts away the complexities of ES6 and CommonJS imports. You can import your files without worrying about underlying implementation details, streamlining your development process and reducing configuration overhead.
  3. Watch Mode:
    Bun features a built-in watch mode, similar to Nodemon. This allows for rapid code changes and automatic reloading, significantly improving the developer’s experience.
  4. Speedy Testing:
    Bun shines when it comes to running unit tests. Benchmarks show that it can execute Jest unit tests much faster than traditional setups, potentially reducing test times from seconds to fractions of a second.
  5. Potential Cost Savings:
    Faster development and testing can lead to substantial cost savings in CI/CD pipelines. Shorter execution times translate to reduced infrastructure costs when running tests on services like GitHub Actions or Circle CI.

Limitations to Consider

While Bun is promising, it’s essential to note its limitations. It might not be suitable for all types of projects, as it relies on JavaScript Core. For example, it currently does not support running projects built with Next.js or Remix, which depend on Node APIs.

Future Possibilities

Despite these limitations, there are exciting possibilities for Bun’s future. Users are exploring options like running Bun on AWS Lambda by wrapping the Bun server in a Docker container, opening up opportunities to use Bun with familiar cloud providers.

Bun presents a compelling alternative for Node.js developers looking to boost their development speed and efficiency. Its focus on performance improvements, simplified imports, and faster testing can make a significant difference in your development workflow. While it may not be a one-size-fits-all solution due to certain limitations, Bun’s potential benefits make it worth considering for your next project. Give it a try and see if it can supercharge your Node.js development experience.

Share
Bun in Fun

JavaScript Objects Cheatsheet

As a follow-up to my previous post on Factory vs Constructor Functions in JavaScript, below is a collection of useful examples that aim to illustrate Objects and their related functionalities.

// Obj literal syntax
const person = { name: 'Behnam', age: 37 };

// Constructor function
function Person(name, age) {
	this.name = name;
	this.age = age;
}
const behnam = new Person('Behnam', 37);

// Class syntax (ES6+)
class Animal {
	constructor(name) {
		this.name = name;
	}
}
const bear = new Animal('Bumzy');

Accessing Object Properties

// Dot notation
console.log(person.name); // Behnam

// Bracket notation
console.log(person['age']); // 37

Modifying Object Properties

person.age = 30; // Changing existing property
person.city = "Stockholm"; // Adding new property
delete person.name; // Deleting a property

Checking if Property Exists

if ('name' in person) {
	console.log("Name exists!");
}

Looping through Obj properties

for (const key in person) {
	console.log(`${key}: ${person[key]}`);
}
// name: Behnam, age: 37

// Object.keys (ES5+)
Object.keys(person).forEach((key) => {
	console.log(`${key}: ${person[key]}`)
});
// name: Behnam, age: 37

Object Methods

const calculator = {
	add: function(a, b) {
		return a + b;
	},
	subtract(a, b) {
		return a - b;
	}
};
console.log(calculator.add(5, 3)); // 8
console.log(cakcykatir.subtract(7, 2)); // 5

Object Serialization

The snippet below first converts the person object into a JSON string using JSON.stringify(). It then parses the JSON string back into a JavaScript object using JSON.parse(). This helps transferring data between different systems.

const json = JSON.stringify(person);
console.log(json); // {"age":37,"name": Behnam}

const obj = JSON.parse(json);
console.log(obj.age); // 37

Inheritance

We’ll create a basic inheritance example involving Person and Student objects.

// Parent object constructor
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// Adding a shared method to the Person prototype
Person.prototype.sayHello = function () {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

// Child object constructor inheriting from Person
function Student(name, age, grade) {
  // Call the Person constructor to set name and age
  Person.call(this, name, age);
  this.grade = grade;
}

// Set up the prototype chain for inheritance
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

// Add a unique method to the Student prototype
Student.prototype.study = function () {
  console.log(`${this.name} is studying in grade ${this.grade}.`);
};

// Create instances of Person and Student
const person = new Person('Alice', 30);
const student = new Student('Bob', 18, 12);

// Use the inherited and unique methods
person.sayHello();
student.sayHello();
student.study();

In this example:

  1. We have a Person constructor function that defines two properties (name and age) and a shared method sayHello().
  2. We then create a Student constructor function that inherits from Person. It calls Person.call(this, name, age) to set the shared properties and uses Object.create(Person.prototype) to set up the prototype chain for inheritance.
  3. The Student constructor adds its unique method study() to its prototype.
  4. We create instances of both Person and Student, and then call their methods to demonstrate inheritance. The Student object inherits the sayHello() method from the Person prototype and has its own study() method.
Share
JavaScript Objects Cheatsheet

Factory vs Constructor Functions

In JavaScript, any function can return a new object. When it’s not a constructor function or class, it’s called a factory function.

Eric Elliot

Two fundamental paradigms stand out in the realm of Javascript fundamentals: factory functions and constructor functions. These two techniques serve as the building blocks for creating objects, each with its own advantages and use cases. In this exploration, I will delve into the world of factory and constructor functions, dissecting their differences, strengths, and when to choose one over the other. Understanding these concepts will undoubtedly enhance your ability to design robust and maintainable code.

TL;DR: The General Purpose of them both is to create your object creation logic once and use either function to create multiple objects. All the credit goes to Sina for his insightful presentation of the concept on his channel, ColorCode.

Factory Function

It creates and returns an object.

function personFactory(n) {
  return { name: n }
}

const me = personFactory('Behnam')

One thing to note here is that here, we are not really using an inheritance hierarchy.

function createPerson(name) {
  return {
    // name: name, // full version
    name, // shorthand version

    talk() {
      return `I am ${this.name}`;
    },
  };
}

const me = createPerson("Behnam");
const you = createPerson("Qoli");

console.log(me); // An instance of the Obj. --> {name: 'Behnam', talk: f}
console.log(you); // An instance of the Obj. --> {name: 'Qoli', talk: f}

me.talk = function () {
  return `Hello, my name is ${this.name}`;
};

console.log(me.talk()); // Hello, my name is Behnam
console.log(you.talk()); // I am Qoli

The Problem with Factory Functions

As mentioned above, we are not really using an inheritance hierarchy.

So the two instances are not pointing to the same thing; they are DIFFERENT.

The Workaround

The Bad Approach

Here is a noteworthy, yet very BAD approach:

Object.prototype.speak = function() { // every object below it will have this speak in their proto
	return 'I can speak'
}

// So, these are all valid and available:
me.speak();
you.speak();

In other words, every object in your application has that method in it! Even if you define it after the fact, like below:

const a = {}; // new object

a.speak(); // Exists! And returns 'I can speak'
window.speak(); // Also exists! BAD IDEA

The Good Approach

Now back to solving the original problem of inheritance, as introduced above. Notice we will return something other than an empty object {}: using Object.create()

const myCoolProto = {
	talk() {
		return `Hello, I am ${this.name}`
	}
}

function createPerson(name) {
	return Object.create(myCoolProto, { // The API of Object.create is a bit different
		name: {
			value: name
		}
	})
}

const me = createPerson("Behnam")

Here is the output:

const myCoolProto = {
  talk() {
    return `Hello, I am ${this.name}`;
  },
};

function createPerson(name) {
  return Object.create(myCoolProto, {
    // The API of Object.create is a bit different
    name: {
      value: name,
    },
  });
}

const me = createPerson("Behnam");
console.log(me);

console.log(me.talk()); // Hello, I am Behnam

Constructor Function

Conventionally, they start with a Capital letter and you call it with a new keyword.

function Person(name) {
	this.name = name
}

const me = new Person('Behnam') // aka an Obj. instantiation

Factory vs Constructor Functions

Below, notice the difference in what they return.

function newPerson(name) { // Factory Fn
  return {
    name: name,
  };
}

const bob = newPerson("Bobby"); // {name: 'Bobby'}

console.log(bob);

function Person(name) { // Constructor Fn
  this.name = name;
}

const me = new Person("Behnam");

console.log(me); // Person {name: Behnam}

NOW WE ARE INHERITING. It means that our Constructor function already comes with its’ OWN PROTOTYPE. In other words, Behnam is now inheriting from Person.

So we can do something like this:

Person.prototype.talk = function () {
  return `Hello, I am ${this.name}`;
};

console.log(me.talk()); // Hello, I am Behnam

const sam = new Person("Sam");
console.log(sam.talk()); // Hello, I am Sam

Summary

A few key facts about Factory Functions:

  • They are just a function.
  • They are a little Simpler.
  • There is no new keyword involved, so there is no this, therefore, they are just simpler.
  • You just return an object!
  • A little more flexible, you are really using the power of closure in a Factory. (aka Data Privacy) See the example below
function createPerson(name) {
  return {
    talk() {
      return `${name}`;
    },
  };
}

const me = createPerson("Behnam");
console.log(me); // only the talk function
console.log(me.talk()); // Behnam
console.log(me.name); // undefined - in other words, it is safe!
// This is what we call data privacy
Share
Factory vs Constructor Functions

TodoJS

todojs-logo

JavaScript is enjoyable, intuitive and the community it’s got is astoundingly huge. For long, I’ve been busy building stuff with Php, which I still do and to me, JavaScript was just a handy-dandy tool to add some spice to the project. Nothing huge. And how I’ve been missing out on all the joy there was.

Sometimes the hard part is just getting going. So I thought the best way to start would be for me to create a little something using the tools like NodeJS, Express, and so forth and see how it goes.

TodoJS

TodoJS turned out to be the palpable evidence that made me realise how little I knew about the veracity of all that hype. Feel free to have a look.

Share
TodoJS