Null vs Undefined

Before we dive too deeply into building components and blocks, you need to understand some important differences in the concept of undefined between C# and JavaScript/TypeScript.

As C# and C developers we often think of null as something that indicates "no value has been set". But in truth we are setting an actual value, the value of null. Because C and C# are compiled languages, there is no concept of undefined because when we click compile it immediately tells us that we have not declared a variable before we tried to use it.

JavaScript extends the concept of undefined beyond just not declaring a variable or property. You can explicitly set and return undefined. Additionally, when decoding data from JSON the property may not be included in the JSON stream which would put it in an undefined state. This is different than C# where that value becomes null - or if the property cannot accept a null value then an exception is thrown.

Therefore, it is important to remember that null and undefined are two distinct values in JavaScript, even though we will likely treat them the same way in most instances. For example, if you declare an interface or type in TypeScript to represent the data you are going to decode from JSON you should declare the property as optional with the "?" suffix. This tells TypeScript that it might actually be undefined. Then when you try to access that property it will enforce that you check if it is defined first.

This means something like a createdDateTime property could have 3 states when we decode it from JSON:

  1. undefined - it wasn't included in the JSON stream.
  2. null - it was included but set to null because C# did not have a value.
  3. string - it was included and the value is of type string.

To account for that, you should declare the property like this:

createdDateTime?: string | null;

This will tell the compiler that you expect the value to be either a string or a null, but it could also be undefined. If you try to use that property before you check the type of value it will warn you.

Now, if we want to use createdDateTime property by passing it to our date parser so we can work with the date value, we would need to do something like:

if (model.createdDateTime !== undefined
    && model.createdDateTime !== null
    && model.createdDateTime !== "") {
    // do something with model.createdDateTime.
}

The final check is because even though the value isn't undefined or null it could still be a zero length string. Depending on your use case you may not need the length check, but remember that just like C#, while a value is a valid string it might also be an empty string which may not be "valid" in your context.

However, what we wrote above is quite verbose and will be tiring. Instead we can, and should, use "truthy" checks to achieve the same result.

if (mode.createdDateTime) {
    // do something with model.createdDateTime.
}

Remember that this truthy check will only pass for a non-empty string, so if you need to take a different action if the string is empty you will need to use a different type of check.

You can use this "truthy table" to get an idea of how JavaScript will respond to the different values when used in a truthy check like the above.