개발일지

[TS] 9. 에러 처리 하기 본문

JS, TS/[TS | 강의] TS·OOP

[TS] 9. 에러 처리 하기

lyjin 2022. 11. 8.

22.09.16 금

Exception과 Error State

  • Exception: 예상할 수 없는 에러들
    • js에서는 Error
    • ex) const array = new Array(100000000000000000);
      • 컴파일 단계에서 확인할 수 없는 error
  • Error State: 예상할 수 있는 에러들

 


Exception:

function move(direction: 'up' | 'down' | 'left') {
  let x: number = 0;
  switch (direction) {
    case 'up':
      x += 1;
      break;
    case 'down':
      x -= 1;
      break;
    default:
      // throw new Error(`unknown direction: ${direction}`);

      const invalid: never = direction;
      throw new Error(`unknown direction: ${invalid}`);
  }
}

/**
* 컴파일 단계에서 에러 잡아주는 것이 좋음 !!
*/
 

Error(Exception) Handling

try > catch > finally

 

function readFile(fileName: string): string {
  if (fileName === 'not exist!💩') {
    throw new Error(`file not exist! ${fileName}`);
  }
  return 'file contents🗒';
}

function closeFile(fileName: string) {
  // ~~~
}

function run() {
  const fileName = 'not exist!💩';

  /** 1. finally 없으면 ?? */
  try {
    console.log(readFile(fileName));
  } catch (error) {
    console.log(`catched!!`);
    return; // closeFile 실행 X
  }

  closeFile(fileName);
  console.log(`closed!`);

  /** 2. finally 사용 */
  try {
    console.log(readFile(fileName));
  } catch (error) {
    // throw new Error()
    console.log(`catched!!`);
    return;        // return 존재 해도 finally 실행 됨!! ⭐️
  } finally {
    closeFile(fileName);
    console.log(`closed!`);
  }
}

run();
  • 참고
    • try는 Error가 발생하는 부분만 감싸는 게 좋다
    • 모든 로직 쑤셔넣지 X

 


Handling:

error handling은 어디에서 하는 게 좋을까 ??

 

예시1)

 

class TimeoutError extends Error {}
class OfflineError extends Error {}

class NetworkClient {
  tryConnect(): void {
    throw new OfflineError('no network!');
  }
}

/** 만약 UserService에서 한다면?
* >> catch 후 수행할 수 있는 의미있는 logic이 존재하지 않음!
*/
class UserService2 {
  constructor(private client: NetworkClient) {}

  login2() {
    try {
      this.client.tryConnect();
    } catch (error) {
      console.log('catched!');
    }
  }
}

class App {
  constructor(private userService: UserService) {}
  run() {
      this.userService.login();
  }
}

const client = new NetworkClient();
const service = new UserService(client);
const app = new App(service);
app.run();

 

 

예시2)

 

class TimeoutError extends Error {}
class OfflineError extends Error {}

class NetworkClient {
  tryConnect(): void {
    throw new OfflineError('no network!');
  }
}

/** 의미 있는 처리 할 수 있는 곳에서 핸들링 하자 */
class UserService {
  constructor(private client: NetworkClient) {}

  login() {
    this.client.tryConnect();
  }
}

class App {
  constructor(private userService: UserService) {}
  run() {
    try {
      this.userService.login();
    } catch (error) {
      // show dialog to use
    }
  }
}

const client = new NetworkClient();
const service = new UserService(client);
const app = new App(service);
app.run();

 

 


State:

  • ts에서 error는 any 타입
    • 세부적인 에러 핸들링 하기 힘들다
class TimeOutError extends Error {}
class OfflineError extends Error {}

class App {
  constructor(private userService: UserService) {}
  run() {
    try {
      this.userService.login();
    } catch (error) { // any
      if (error instanceof TimeOutError) { ⭐️
        // 사용 불가
        // ES6 이상은 가능!!! ⭐️
      }
    }
  }
}

 

type NetworkErrorState = {
  result: 'fail';
  reason: 'offline' | 'down' | 'timeout';
};

type SuccessState = {
  result: 'success';
};

type ResultState = SuccessState | NetworkErrorState;

class NetworkClient {
  tryConnect(): ResultState {
    return {
      result: 'success',
    };
  }
}

class UserService {
  constructor(private client: NetworkClient) {}

  login() {
    return this.client.tryConnect();
  }
}

class App {
  constructor(private userService: UserService) {}

  run(): ResultState {
    try {
      return this.userService.login();
    } catch (error) {
      return {
        result: 'fail',
        reason: 'offline',
      };
    }
  }
}

const client = new NetworkClient();
const service = new UserService(client);
const app = new App(service);
app.run();