If I am using (strict null checks) TypeScript, and I have some code with a possibly null variable:
let x = null;
if (someCondition) {
x = { a: 1 };
}
doSomethingWith(x.a);
I get an error, as expected:
‘x’ is possibly ‘null’.
I can fix that error with a null check:
if (!x) return;
doSomethingWith(x.a);
but then I get:
Property ‘a’ does not exist on type ‘never’.
And really, instead of an if/return, what I’d like to write is an assert call:
const assert = value => { if (!value) throw Error(); }
assert(x);
doSomethingWith(x.a);
… but that doesn’t even get rid of the first error.
I figured out that I could fix the second error with:
(rootGroup as {id: number}).id
but I’m not sure if all that is the simplest solution, and it still doesn’t solve the problem with using an assert function.
My question is, how can I …?
- create a "maybe null" variable
- run a function that proves it’s not null (by throwing an error if it is)
- add (the least amount possible of) TypeScript code, and then
- use that variable, without any TS errors
>Solution :
You can use assertion signatures like this:
let x: { a: 1 } | null = null
if (someCondition) {
x = { a: 1 }
}
// @ts-expect-error x maybe null
console.log(x.a)
assert(x) // asserting that x is truthy
console.log(x.a) // no error here
function assert(value: unknown): asserts value {
if (!value) {
throw new Error('foo')
}
}
If you just want to throw on nullish values, you can do something like this:
function assertNotNull<T>(value: T): asserts value is NonNullable<T> {
if (value == null) {
throw new Error('bar')
}
}