Ts Null Undefined
In TypeScript, null and undefined have special handling.
After enabling `strictNullChecks`, you need to explicitly handle these values, which helps write safer code.
* * *
* * *
## Why You Need to Handle null and undefined
In JavaScript, null and undefined are common sources of errors, and many runtime errors are related to them.
TypeScript's strictNullChecks option requires developers to explicitly handle values that may be null.
Although this increases coding workload, it can significantly reduce runtime errors caused by null values and improve code reliability.
> **Concept Explanation:** `null` represents "empty value", meaning there is no value here; `undefined` represents "undefined", meaning it hasn't been assigned a value yet.
* * *
## null and undefined Basics
null represents "empty value", undefined represents "undefined". Both are independent types in TypeScript.
## Example
// Declare a variable of null type
// Can only be assigned null
var empty:null=null;
// Declare a variable of undefined type
// Can only be assigned undefined
var notDefined:undefined=undefined;
console.log("null: "+ empty);
console.log("undefined: "+ notDefined);
**Output:**
null: nullundefined: undefined
> **Note:** Without enabling strictNullChecks, these types can be assigned to each other. After enabling, explicit declaration is required.
* * *
## Union Type Handling for null
After enabling strictNullChecks, you need to use union types to explicitly declare values that may be null.
## Example
// Union type: can be string or null
// Explicitly declare that the value may be null
var name: string |null="Alice";
name =null;// Correct: can be assigned null
// Accessing possibly null values requires checking first
// Function parameter may be string or null
function getLength(str: string |null): number {
// Use conditional check for null
if(str ===null){
return 0;// Return 0 when null
}
// TypeScript infers str is not null
return str.length;
}
console.log("Length: "+ getLength("hello"));
console.log("Length: "+ getLength(null));
**Output:**
Length: 5Length: 0
> **Best Practice:** Use type guards (if check) to narrow the type, so TypeScript knows the specific type.
* * *
## Optional Parameters and Properties
Optional parameters and optional properties automatically include undefined, without needing explicit null declaration.
## Example
// Optional parameter: use ? to mark
// Parameter may be string or undefined
function greet(name?: string): string {
// Check for undefined
if(name ===undefined){
return"Hello, stranger!";
}
return"Hello, "+ name;
}
console.log(greet("Alice"));
console.log(greet());
// Optional property: use ? to mark
// age property is optional, may not exist
interface User {
name: string;
age?: number;// Optional property
}
var user: User ={ name:"Bob"};
console.log("User: "+ JSON.stringify(user));
**Output:**
Hello, Alice!Hello, stranger!User: {"name":"Bob"}
> **Note:** Optional parameter `name?: string` is equivalent to `string | undefined`.
* * *
## Non-null Assertion Operator
Use `!` to tell the compiler the value is not null or undefined. This should be used cautiously.
## Example
function getLength(str: string |null): number {
// Non-null assertion: tell compiler str is not null
// This is a dangerousimplementation, if str is actually null it will error
return str!.length;
}
console.log("Length: "+ getLength("hello"));
> **Warning:** Non-null assertion bypasses TypeScript's type checking, if the value is actually null, it will still error at runtime. Avoid using it as much as possible.
* * *
## Nullish Coalescing Operator
Use `??` to provide a default value, only using the default when the value is null or undefined.
## Example
// Initial value is null
var name: string |null=null;
// ?? operator: use right value when left is null/undefined
// If name is null, use "Guest"
var displayName = name ??"Guest";
console.log("Display Name: "+ displayName);
// Compare with || operator (treats 0 and empty string as falsy)
var num: number |null=0;
var result1 = num ??100;// 0 (correct: 0 is not null/undefined)
var result2 = num ||100;// 100 (wrong: 0 is treated as falsy)
console.log("?? Result: "+ result1);
console.log("|| Result: "+ result2);
**Output:**
Display Name: Guest?? Result: 0|| Result: 100
> **Suggestion:** Prefer using `??` over `||`, because `??` only handles null and undefined, and won't incorrectly treat 0 or empty string as falsy.
* * *
## Optional Chaining
Use `?.` to safely access possibly non-existent nested properties, avoidingNull checking for deeply nested objects.
## Example
// Define person type, address is optional
interface Person {
name: string;
address?:{
city: string;
};
}
// Create person object, no address
var person: Person ={ name:"Alice"};
// Optional chaining: safely access possibly non-existent property
// If address doesn't exist, returns undefined without error
var city = person.address?.city;
// Combine with nullish coalescing operator
console.log("City: "+ city);
console.log("City: "+(person.address?.city??"Unknown"));
**Output:**
City: undefinedCity: Unknown
> **Best Practice:** Optional chaining `?.` is the best way to handle nested optional properties, combined with `??` can provide default value fallback.
* * *
## Notes
* **Strict Mode:** It is recommended to enable strictNullChecks for better type safety
* **Avoid Assertion:** Try not to use non-null assertion `!`
* **?? vs ||:** Prefer using `??` to avoid misjudging 0 and empty strings
* **Optional Chaining:** Use `?.` when handling nested optional properties
YouTip