I am trying to create a function like this:
function assert<T>(condition: T, msg?: string): T & asserts condition {
if (!condition) {
throw new Error(msg)
}
return condition
}
The goal is to return condition unmodified, preserving its type, but also informing the compiler that the returned value is truthy. This would allow it to be used as a standalone statement, but also unobtrusively inside an expression:
const success: bool = true
// ... some code that might set success = false
assert(success)
const element: HTMLElement = assert(document.getElementById('foo'))
Unfortunately, the above syntax does not work (playground). Is there a way to express this in TypeScript?
I can't find any official documentation on assertion functions except the Release notes for TypeScript 3.7, and those only demonstrate assertion functions that implicitly return void.
The best I can come up with is a workaround for object types only, because those can never be falsy:
function assert<T extends object>(condition: T | null | undefined, msg?: string): T {
if (!condition) {
throw new Error(msg)
}
return condition
}