[TypeScript] null의 개념과 활용

null이란

null은 JavaScript에서 값이 없음을 명확하게 표현하는 값입니다. TypeScript에서도 이 의미는 동일하게 유지되며, 변수에 값이 아직 할당되지 않았거나 명시적으로 비어 있음을 표현할 때 사용됩니다. 예를 들어, DOM 요소를 찾을 때 해당 요소가 존재하지 않으면 null이 반환됩니다. TypeScript에서는 null을 타입으로도 사용할 수 있어서, 변수가 null 값을 가질 수 있는지 명시적으로 정의할 수 있습니다.

null의 기본 동작

TypeScript는 기본적으로 타입 안정성을 보장하려고 노력합니다. 하지만 JavaScript와의 호환성을 위해 null과 undefined는 모든 타입에 암묵적으로 포함되지 않습니다.  이를 엄격하게 관리하려면 strictNullChecks 설정을 활성화해야 합니다. 이 설정이 꺼져 있으면, 모든 타입이 null이나 undefined를 허용하게 되어 타입 안정성이 약화될 수 있습니다.

strictNullChecks off

let name: string = null; // 문제없이 동작
console.log(name); // null

strictNullChecks on

let name: string = null; // 오류: Type 'null' is not assignable to type 'string'

이 설정을 통해 null이 의도치 않게 들어가는 실수를 방지할 수 있습니다.

null 확인 방

null 여부를 확인할 때는 typeof 연산자를 사용할 수 없습니다. typeof를 사용하면 null"object"로 반환되기 때문입니다.

올바른 방법은 == 또는 === 연산자를 사용하는 것입니다.

let emptyValue: null = null;

console.log(typeof emptyValue); // "object" (주의 필요)

// 동등 연산자(==) 사용 시
console.log(emptyValue == null); // true
console.log(emptyValue == undefined); // true

// 엄격한 동등 연산자(===) 사용 시
console.log(emptyValue === null); // true
console.log(emptyValue === undefined); // false

== 연산자는 nullundefined를 동일하게 취급하지만, === 연산자는 엄격한 비교를 수행하므로 차이를 정확하게 구분할 수 있습니다.

유니온 타입으로 정의한 null 허용

interface User {
  id: number;
  name: string;
}

async function fetchUser(userId: number): Promise<User | null> {
  const response = await fetch(`/api/users/${userId}`);
  if (!response.ok) {
    return null; // 사용자 데이터가 없으면 null 반환
  }
  return response.json();
}

async function displayUser(userId: number) {
  const user = await fetchUser(userId);
  if (user === null) {
    console.log("사용자를 찾을 수 없습니다.");
    return;
  }
  console.log(`안녕하세요, ${user.name}님!`);
}

옵셔널 체이닝과 함께 사용하는 null

interface Profile {
  address?: {
    city: string;
    country: string;
  };
}

const profile: Profile | null = getProfile(); // 외부에서 받아왔다고 가정
const city = profile?.address?.city ?? "알 수 없음";
console.log(city); // profile이나 address가 null이면 "알 수 없음" 출력