I was very enthusiastic about writing notes but I was afraid to start. Sometimes don’t know what to write? Sometimes when you write something, you are afraid to show your shyness. You have been working for 8 or 9 years and still write something so low. Inspired by reading how to eliminate the pain of writing and make it enjoyable. I decided to keep a timely record of the problems I encountered at work. Well, I’m not a trailblazer, I’m just a chronicler.

The cause of

After observing online monitoring for some time (currently our company uses Sentry), I found that most of the errors are

TypeError: Cannot read property 'xxx' of undefined
Copy the code

There are two common reasons for this error:

  1. When writing code, do not pay attention to the boundary case, such as the front and back end of the data entity field defined by the normal value, but because of one side of the negligence, a data entity returnsnullor{}
  2. In the process of functional iteration, some code, such as: definition, was ignored when the structure of the data entity was changedStaffField isStaff: { Department: {... }}, after iterationDepartmentChanged toIdReference, that is,Staff: {Department: xxxxxxxx}

Both of these situations are very common in a rapidly iterating business.

TS previous solution

Native JS solutions:

if (Staff && Staff.Department && Staff.Department.Name) {
  // your code here
}
Copy the code

In addition to the 👆 method above, lodash provides a get method to solve this problem.

Gets the value at path of object. If the resolved value is undefined, the defaultValue is returned in its place.

Gets the value based on the path of the object. If the parse value is undefined, return a defaultValue.

Using the GET method, the code above can be simplified to

_.get(Staff, `Staff.Department.Name`."DefaultName");
Copy the code

For details, go to ➡️ : Lodash get

“Optional chain” and “Null Value Merge” of TS

TypeScript 3.7 solves this problem more gracefully with two new language features: Optional Chaining and the Nullish coalescing operator.

So what is an optional chain? Essentially, with optional chains, we can write code that immediately stops certain expressions if we encounter null or undefined. Is the core of the optional chain new? Operator for optional property access. The code can become

if(Staff? .Department? .Name){// your code here
}
Copy the code

So? Is it equivalent? The answer is no. && also contains cases that are cast to Boolean values (such as empty strings, 0, NaN, and false)

Common ways to select chains

grammar

Three “postures” for optional chains

obj? .prop// Property accessobj? .[expr]// Optional element accessfunc? . (... args)// Optional function or method call
Copy the code

Give an example of how to use it

type UserResponse = {
  firstName: string
  lastName: string
  age: numberoccupation? :stringjobHistory? : { firstJob? :string}, favoriteFoods? :string[]}const user: UserResponse;

// without optional chaining 🤢
const userOccupation = user && user.occupation;

// with optional chaining ❤️
constuserOccupation = user? .occupation;constuserOccupation = user? ."occupation"];
// or
constfavFood = user? .favoriteFoods? .0];

Copy the code

Third case: Optional function or method calls

Optional chains can also be used in function calls. They come in handy when you need to call a function conditionally at runtime, that is, only if the function exists. This can be done like this.

const callFakeApi = async (url: string, log? :(user: object) = > void) = > {const response = await fetch(url);
  const data = awaitresponse.json(); log? .(data); } callFakeApi('https://jsonplaceholder.typicode.com/todos/1'.console.log);
Copy the code

A null value merge

Nullish Coalescing is another new feature in TypeScript 3.7 that is closely related to Optional Chaining. It uses a unique operator:?? When an expression returns null or undefined, it is used as the default or “fallback” value.

Usage:

// null value
null || 20 // returns 20
null ?? 20 // returns 20

// undefined value
undefined || 20 // returns 20
undefined ?? 20 // returns 20

// boolean
true ?? 10 // returns true
false ?? 10 // returns false

// NaN
NaN ?? 20 // returns NaN

// empty string
' ' ?? 5 // returns ''
Copy the code

Pay special attention to and the commonly used | | difference:?????? Come into force only to null, and undefined, but | | for compulsory converted to Boolean values are effective. To illustrate a scenario, the following code snippet attempts to read the last stored value (if any) from localStorage; However, because use the | |. It is a bug:

unction initializeAudio() {
  let volume = localStorage.volume || 0.5;
  // ...
}
Copy the code

When localstorage. volume is set to 0, the volume variable will be set to 0.5, which is obviously not what we want. ?? Avoid unexpected behavior caused by false values such as 0, NaN, and “”.

The resources

  1. Lodash’s get method
  2. Optional Chaining and Nullish Coalescing in TypeScript
  3. Typescript Optional Chaining