There are many factors that contribute to null being a "Billion Dollar Mistake". Based on your comments, you're looking specifically at TypeScript and the type of possibly-uninitialized values, so I'll boil it down to two key problems: type safety, and value semantics.
The key - a.k.a., tl;dr
Especially in TypeScript, null-ish values are perfectly valid so long as you assign a simple, clear meaning to it ("no value"), and so long as the language supports this by only permitting null-ish values when the type explicitly allows it.
TypeScript naturally guards against accidental null values.
Others have covered type safety, but the key here is that, in TypeScript, you can include or exclude null and undefined as valid values of a type. At least in strict mode, number, number | null, and number | undefined are all separate types. Types are mathematical sets of valid values, and number only covers numbers. That means that (barring any deliberate breaking of the type system), you don't have to worry about a value unexpectedly being null or undefined. The compiler won't let you accidentally do that. In that regard, the type safety of null-like values is not such a big deal in TypeScript, which just leaves semantics.
So what do null and undefined mean?
In short, they mean "no value" - nothing more, nothing less. The number type can be any number, but it must be a number. In some cases, you want a type that's "a number, or nothing" - that's where you might use number | undefined. If you want something other than "has a value or doesn't" - such as "technically a value, but invalid" or "there was an error trying to compute the value", you need to use something other than null or undefined. The exact solution depends on the exact use case - over-generalizing is what caused the problem in the first place!
So why are there two?
This illustrates the "semantics" problem of the Billion Dollar Mistake quite well! Your colleague was right to point out that, in JavaScript, undefined means "was never defined", and shouldn't be allowed after initialization. That leaves null to mean... anything else that isn't a real value? However, TypeScript is not JavaScript! Believe it or not, the team who creates TypeScript (which is, itself, written in TypeScript) does not use null at all! These experts in the topics of language and especially of TypeScript and JavaScript have decided that null does not provide any value above and beyond undefined. But they do use undefined.
I don't want to misrepresent them, but I believe that this is because they're focusing on what those values mean above and beyond how the JavaScript engines use them. Now, undefined simply means "no value". They don't want to add any more than that, so they don't recognize a difference between that and null.
What does this mean for my example?
There's some missing information about what null is supposed to mean, but you seem to be doing the right thing. However, I would ditch the type Value = Node | null and also switch to undefined. Something like:
const [value, setValue] = React.useState<Node | undefined>()
function test(value: Node | undefined) {
if (value != undefined) // TS knows v is a Node, not undefined
else // TS knows v is undefined
}
Bonus: ? operator vs explicit undefined
You can use ? when declaring a value's identifier to suggest that it's optional. This automatically means it can be undefined (as that is the default for when a value is not provided), but it means more than that. function test(value: Node | undefined) means "test requires one argument, which may be undefined", whereas test(value?: Node) means "test can be called with 0 arguments, or with a Node, or with undefined". It's a small difference, but sometimes you want to say "you must tell me what it is, even if you tell me there's no value", in which case you should avoid ?.
nullis only a mistake if you don't know how to deal with it correctly. One way to deal with it correctly is to make sure all of your object references always have a value. Hence, your colleague's argument. – Robert Harvey Jul 26 '20 at 23:18