I have created this playground and here is the code:
type BundlerError = Error;
type BundlerWarning = Error;
export type BundlerState =
| { type: 'UNBUNDLED' }
| { type: 'BUILDING'; warnings: BundlerWarning[] }
| { type: 'GREEN'; path: string; warnings: BundlerWarning[] }
| { type: 'ERRORED'; error: BundlerError }
const logEvent = (event: BundlerState) => {
switch (event.type) {
case 'UNBUNDLED': {
console.log('received bundler start');
break;
}
case 'BUILDING':
console.log('build started');
break;
case 'GREEN':
if(event.warnings.length > 0) {
console.log('received the following bundler warning');
for (let warning of event.warnings) {
warning
console.log(warning.message);
}
}
console.log("build successful!");
console.log('manifest ready');
break;
case 'ERRORED':
console.log("received build error:");
console.log(event.error.message);
break;
}
}
BundlerState is a discriminated union and the switch narrows the type.
The problem is that it does not scale and big expanding switch statements are pretty horrible.
Is there a better way I can write this and still keep the nice type narrowing?
You cannot do this:
const eventHandlers = {
BUNDLED: (event: BundlerState) => event.type // type is not narrowed
// etc,
};
const logEvent = (event: BundlerState) => eventHandlers['BUNDLED'](event);
Because the type is not narrowed.