Hi, I'm oreo, a front-end engineer from iCARE Co., Ltd.

Our front end is developed with Vue.js, TypeScript. In a certain PR, we received the following review from our technical advisor .

I was worried when refactoring, but I saw some unnecessary parts with? Cast! |? | As are all dangerous codes and the burden on the reviewer is heavy, so only the parts that are necessary properly Please be careful to put it in

I've been using it easily so far , so I'd like to sort out their behavior!

?about

Optional parameter ( ?)

Overview

If you add an optional parameter to the argument , that argument can be omitted . In Example 1.1, if test()you execute, you Expected 1 arguments, but got 0. will get angry , but if you add an optional parameter (Example 1.2), you will not get angry.

//例1.1
const test = (x:number,y:number):void=>{
  console.log(x);
};
test(1); //エラー Expected 2 arguments, but got 1.

//例1.2
const test = (x:number,y?:number):void=>{
  console.log(x);
}
test(1);  //OK

important point

  • In Example 1.2, when the optional parameter is used, the argument x is string | undefinedrecognized as a union type of .
  • Also, optional parameters must always be written at the end of the argument (Example 1.3).
    //例1.3
    const test = (x?:number,y:number):void=>{
      console.log(x,y);
    };
    
    //エラー A required parameter cannot follow an optional parameter.

Supplement: Default parameters

You can also give default values ​​to optional parameters by writing something like ?. Also, the default parameter does not have to be written at the end of the argument.

//例1.4
const test = (x: number, y = 3): void => {
  console.log(x+y);
  console.log(x);
};

test(1); //OK

// console.log(x+y)は4と出力
// console.log(x)は1と出力

Optional chaining ( ?.)

Overview

Available in TypeScript 3.7 and above. nullAnd undefienwith respect to the property .Referring the error occurs (for example, 2.1) is, ?.and use, the error does not occur, undefiendit is returned (for example, 2.2) .

//例2.1
type Address = {
      prefecture: {
        name: string
        city?: {
          name: string
        }
      }
    }
    
const address: Address = {
      prefecture: {
        name: 'tokyo',
      },
    }
const targetAddress = address.prefecture.city.name //エラー Object is possibly 'undefined'.
console.log(targetAddress)

//例2.2
type Address = {
      prefecture: {
        name: string
        city?: {
          name: string
        }
      }
    }
const address: Address = {
      prefecture: {
        name: 'tokyo',
      },
    }
const targetAddress = address.prefecture.city?.name //OK
console.log(targetAddress)

important point

  • ?.If you use, it will be evaluated short-circuited . Under short-circuit evaluation, ?.the left side than the nullkilling undefiendcase of, ?.you more right-hand side is no longer evaluated (executed).

Null coalescing operator ( ??)

Overview

Available in TypeScript 3.7 and above. Returns the right value if the left side is nullor undefiend, otherwise returns the left value (Example 3.1).

//例3.1
const name = null ?? 'Yamada Taro';
console.log(name);
//  'Yamada Taro'が出力

important point

??Returns the value on the left, ||unlike the OR operator , nullor undefiendfor falsy values ​​other than (for example, ''or 0) .

//例3.2 OR演算子
const age = 0 || 18;
console.log(age);
// 18が出力

//例3.3 Null合体演算子
const age = 0 ?? 18;
console.log(age);
// 0が出力

Null coalescing operator ( ??=)

Overview

Available in TypeScript 4.0 and above. Substitute if the left side is nullorundefiend (Example 4.1).

//例4.1
const pilot = { name: null };

pilot.name ??= "shinji";
console.log(pilot.name); //shinjiが出力

//例4.2 
const pilot = { name: "shinji" };

pilot.name ??= "asuka";
console.log(pilot.name); //shinjiが出力。asukaが代入されない。

The two lines in Example 4.3 give the same result.

const pilot = { name: null };

//例4.3
pilot.name ??= "shinji"; //Null合体代入演算子
pilot.name = pilot.name ?? "shinji"; //Null合体演算子

important point

The left-hand side is null, or undefiendthe case of falsy a value other than (for example, ''Ya 0), not assigned .

//例4.4
const pilot = { age: 0 };
pilot.age ??= 14; 
console.log(pilot.age) //0が出力

!about

Non-null assertion operator ( !)

Overview

For nullable types ( T | nullor T | null | undefiend), !you can use non-null assertions ( ) to make it clear to the compiler that the type null | undefiendis notT .

//例5.1
type Dog = { name: string };
const mydog = { name: "sora" };

const getDog = (dog?: Dog) => {
  console.log(dog.name); //エラー Object is possibly 'undefiend'
};
getDog(mydog);

//例5.2
type Dog = { name: string };
const mydog = { name: "sora" };

const getDog = (dog?: Dog) => {
  console.log(dog!.name); //OK
};
getDog(mydog);

important point

It null | undefiendmay be better not to use it too much, because it may make it clear that it is not compulsory and you may not notice the change in type.

Clear Assignment Assertion ( !)

Overview

If a variable may not have been assigned a value (if TypeScript cannot be statically detected), as in Example 6.1, you will be offended by using that variable. However, !you can use to make it clear to the compiler that a variable has been assigned a value by the time you use it.

//例6.1
let name: string;

const addName = (val: string) => {
  name = val;
};
addName("shinji");

console.log(name); //エラー Variable 'name' is used before being assigned.

//例6.2
let name!: string;

const addName = (val: string) => {
  name = val;
};
addName("shinji");

console.log(name); //OK

important point

If the variable is not assigned due to a code change etc., you will not notice it, so basically it may be better not to use it too much.

Finally

By summarizing it again, my mind was organized. ?, !Is very convenient, but you should use it after fully understanding its danger (notice the change of type etc.). In addition, among the team members, ?, !I thought also the kana break-and coding rules for clarification is also an important level of understanding about.

reference

O'Reilly Japan, Inc. "Programming TypeScript"

Author: oreo2990