Type Guard "Switch" vs Map (v3)

Revision 3 of this benchmark created on


Setup

function isX(thing) {
	return thing.type === 'x';
}

function doX(thing) {
	thing.value += 1;
}

function isY(thing) {
	return thing.type === 'y';
}

function doY(thing) {
	thing.value += 'hello';
}

function isZ(thing) {
	return thing.type === 'z';
}

function doZ(thing) {
	thing.value = !thing.value;
}

function isA(thing) {
	return thing.type === 'a';
}

function doA(thing) {
	thing.value = false;
}

function isB(thing) {
	return thing.type === 'b';
}

function doB(thing) {
	thing.value += 100;
}

function isC(thing) {
	return thing.type === 'c';
}

function doC(thing) {
	thing.value += '?';
}

function isD(thing) {
	return thing.type === 'd';
}

function doD(thing) {
	thing.value += 'D';
}

function isE(thing) {
	return thing.type === 'e';
}

function doE(thing) {
	thing.value += 'E';
}

function isF(thing) {
	return thing.type === 'f';
}

function doF(thing) {
	thing.value += 'F';
}

function isG(thing) {
	return thing.type === 'g';
}

function doG(thing) {
	thing.value += 'G';
}

function isH(thing) {
	return thing.type === 'h';
}

function doH(thing) {
	thing.value += 'H';
}

function isI(thing) {
	return thing.type === 'i';
}

function doI(thing) {
	thing.value += 'I';
}

const lookup = new Map([
  ['x', (thing) => {
  	if (isX(thing)) {
  		doX(thing);
  	} else {
  		throw 'NOT X';
  	}
  }],
  ['y', (thing) => {
  	if (isY(thing)) {
  		doY(thing);
  	} else {
  		throw 'NOT Y';
  	}
  }],
  ['z', (thing) => {
  	if (isZ(thing)) {
  		doZ(thing);
  	} else {
  		throw 'NOT Z';
  	}
  }],
  ['a', (thing) => {
  	if (isA(thing)) {
  		doA(thing);
  	} else {
  		throw 'NOT A';
  	}
  }],
  ['b', (thing) => {
  	if (isB(thing)) {
  		doB(thing);
  	} else {
  		throw 'NOT B';
  	}
  }],
  ['c', (thing) => {
  	if (isC(thing)) {
  		doC(thing);
  	} else {
  		throw 'NOT C';
  	}
  }],
  ['d', (thing) => {
  	if (isD(thing)) {
  		doD(thing);
  	} else {
  		throw 'NOT D';
  	}
  }],
  ['e', (thing) => {
  	if (isE(thing)) {
  		doE(thing);
  	} else {
  		throw 'NOT E';
  	}
  }],
  ['f', (thing) => {
  	if (isF(thing)) {
  		doF(thing);
  	} else {
  		throw 'NOT F';
  	}
  }],
  ['g', (thing) => {
  	if (isG(thing)) {
  		doG(thing);
  	} else {
  		throw 'NOT G';
  	}
  }],
  ['h', (thing) => {
  	if (isH(thing)) {
  		doH(thing);
  	} else {
  		throw 'NOT H';
  	}
  }],
  ['i', (thing) => {
  	if (isI(thing)) {
  		doI(thing);
  	} else {
  		throw 'NOT I';
  	}
  }]
]);

// populates either number, string or boolean
const things = [];
for (let i = 0; i < 1000; i++) {
	switch (i % 12) {
		case 0:
			things.push({
				type: 'x',
				value: i
			});
			break;
		case 1:
			things.push({
				type: 'y',
				value: i.toString()
			});
			break;
		case 2:
			things.push({
				type: 'z',
				value: Math.random() > 0.5
			});
			break;
		case 3:
			things.push({
				type: 'a',
				value: Math.random() > 0.5
			});
			break;
		case 4:
			things.push({
				type: 'b',
				value: i
			});
			break;
		case 5:
			things.push({
				type: 'c',
				value: i.toString()
			});
			break;
		case 6:
			things.push({
				type: 'd',
				value: i.toString()
			});
			break;
		case 7:
			things.push({
				type: 'e',
				value: i.toString()
			});
			break;
		case 8:
			things.push({
				type: 'f',
				value: i.toString()
			});
			break;
		case 9:
			things.push({
				type: 'g',
				value: i.toString()
			});
			break;
		case 10:
			things.push({
				type: 'h',
				value: i.toString()
			});
			break;
		case 11:
			things.push({
				type: 'i',
				value: i.toString()
			});
			break;
	}
}

Teardown

things.splice(0, things.length);

Test runner

Ready to run.

Testing in
TestOps/sec
Type Guard "Switch"
for (const thing of things) {
	if (isX(thing)) {
		doX(thing);
	} else if (isY(thing)) {
		doY(thing);
	} else if (isZ(thing)) {
		doZ(thing);
	} else if (isA(thing)) {
		doA(thing);
	} else if (isB(thing)) {
		doB(thing);
	} else if (isC(thing)) {
		doC(thing);
	} else if (isD(thing)) {
		doD(thing);
	} else if (isE(thing)) {
		doE(thing);
	} else if (isF(thing)) {
		doF(thing);
	} else if (isG(thing)) {
		doG(thing);
	} else if (isH(thing)) {
		doH(thing);
	} else if (isI(thing)) {
		doI(thing);
	} else {
		throw 'NO TYPE FOUND';
	}
}
ready
Map
for (const thing of things) {
	const runner = lookup.get(thing.type);
	if (runner) {
		runner(thing);
	} else {
		throw 'NO TYPE FOUND';
	}
}
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.