kota's memex

typescript Just fucking use it lol

strict mode

Place "use strict" at the top of a file or function to cause js to print an error rather than creating global variables or other silly things:

testing

ava

A popular, fast, and minimal test runner.

manual testing

If you don't want to rely on a framework you can write little test programs yourself fairly easily. This example tests toUperCase:

function test(label, body) {
	if (!body()) {
		console.log(`Failed: ${label}`)
	} else {
		console.log(`Passed: ${label}`)
	}
}

test("convert Latin test to uppercase", () => {
	return "hello".toUpperCase() == "HELLO"
})

test("convert nothing to uppercase", () => {
	return "".toUpperCase() == ""
})

test("convert spaces to uppercase", () => {
	return "    ".toUpperCase() == "    "
})

exceptions

Exceptions are used when a function cannot proceed normally to jump to a place that knows how to handle the problem. First you "raise" an exception, which can be any value, and execution is moved out of the current function down the call stack until a "catch" is encountered. It's a bit like a overcharged function return.

If an error is not caught it will instead be handled by the environment. In browsers, a description of the error is typically logged to the console. In Node.js the whole process is aborted when an unhandled exception occurs.

function promptDirection(question) {
	let result = prompt(question)
	if (result.toLowerCase() == "left") return "L"
	if (result.toLowerCase() == "right") return "R"
	throw new Error("Invalid direction: " + result)
}

function look() {
	if (promptDirection("Which way?") == "L") {
		return "a house"
	} else {
		return "two angry bears"
	}
}

try {
	console.log("You see", look())
} catch (error) {
	console.log("Something went wrong: " + error)
}

The Error constructor creates an object with a message property. In most js environments, instances of this constructor also contain a stack property with a stack trace.

catch

When a catch body is entered, all we know is that something in out try body caused an exception. But we don't know what did or which exception it caused. In a rather glaring omission, javascript doesn't provide direct support for selectively catching exceptions: either you catch them all or you don't catch any. This makes it tempting to assume that the exception you get is the one you were thinking about when you wrote the catch block. But it might not be.

In this example promptDirection is misspelled so the exception being raised isn't that an invalid direction was entered as we're assuming:

for (;;) {
	try {
		let dir = promtDirection("Where?")
		console.log("You chose ", dir)
		break
	} catch (e) {
		console.log("Not a valid direction. Try again.")
	}
}

custom errors

Often times when catching an error you need to catch a specific type of error and ignore others such as a misspelled method call. To do this you should create a new class extending Error and use instanceof in the catch statement.

class InputError extends Error {}

function promtDirection(question) {
	let result = prompt(question)
	if (result.toLowerCase() == "left") return "L"
	if (result.toLowerCase() == "right") return "R"
	throw new InputError("invalid direction: " + result)
}

for (;;) {
	try {
		let dir = promptDirection("Where?")
		console.log("You chose ", dir)
		break
	} catch (e) {
		if (e instanceof InputError) {
			console.log("Not a valid direction. Try again.")
		} else {
			throw e
		}
	}
}

assertions

Assertions are checks inside a program that verify that something is the way it is supposed to be. They are not to handle situations that can come up in normal operation, but to find programmer mistakes. For example, if firstElement is a function that should never be called on empty arrays, we could write this:

function firstElement(array) {
	if (array.length == 0) {
		throw new Error("firstElement called with empty array []")
	}
	return array[0]
}