Took some time off this weekend to learn some TypeScript, and reimplemented some data structures as practice.
I don’t think I’ll continue to use much TypeScript moving forward, because it seems to promote the classical inheritance style of thinking in a language that doesn’t need or want it.
TL;DR: Prototypical/concatenative inheritance is much nicer than classical inheritance.
That said, first-class support for TypeScript in Visual Studio Code is quite awesome. While implementing the data structures, I came up with a TypeScript/prototypical hybrid style for writing object factories. In this hybrid style, the only place I’m writing any TypeScript is using interfaces for prototypes. Let’s take a number
class for example:
interface NumberInterface {
isEven() : boolean
multiplyByTwo() : number
divideBy(arg: number) : number
}
const number = (num: number) => {
const prototype: NumberInterface = {
isEven() {
return this.number % 2 === 0
},
multiplyByTwo() {
return this.number * 2
},
divideBy(arg) {
if (arg === 0) {
throw new Error('Cannot divide by 0')
}
return this.number / arg
}
}
return Object.assign(Object.create(prototype), { number: num })
}
const two = number(2)
console.log(two.isEven()) // true
console.log(two.multiplyByTwo()) // 4
console.log(two.divideBy(2)) // 1
console.log(two.divideBy(0)) // Error: Cannot divide by 0
I return a object whose prototype is prototype
using Object.create
, and its initial state using Object.assign
.
This style allows VSC to shout at me if the prototype doesn’t implement the interface correctly. It’s nice to have, but not worth switching over to a TypeScript workflow from the Babel workflow that I’m already used to.