본문 바로가기
C.W.K.
Stream
Lesson 02 of 05 · published

instanceof와 in: 인스턴스와 객체 모양을 좁히기

~9 min · narrowing, instanceof, in, classes

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"클래스 정체를 묻는 질문과 속성 존재를 묻는 질문은 다르다. 값에 맞는 질문을 골라."

instanceof는 프로토타입을 확인해

x instanceof Date는 실행 중 x의 프로토타입 연결에 Date.prototype이 있는지 확인해. TypeScript는 참인 분기에서 x를 Date로 좁혀 toISOString 같은 메서드를 사용할 수 있게 해. Error, Map, 사용자 정의 클래스에도 같은 방식이 적용돼.

plain 객체는 클래스 생성자를 거치지 않았으므로 모양이 같아도 instanceof에 잡히지 않아. 서로 다른 iframe 같은 실행 영역에서 만들어진 값은 생성자 정체가 달라질 수 있다는 점도 알아 둬. 배열에는 영역 문제를 피하는 Array.isArray가 더 안전해.

in은 속성의 존재를 확인해

'id' in item은 item 자체나 프로토타입 연결에 id 속성이 있는지 실행 중 확인해. 객체 유니언 가운데 id를 가진 변형과 그렇지 않은 변형을 가르는 증거로 사용할 수 있어.

선택 속성이 여러 변형에 걸쳐 있으면 거짓 분기에서 완전히 제거되지 않을 수 있어. 또한 속성이 존재하지만 값이 undefined인 경우도 참이야. ‘키가 있는가’와 ‘값이 유효한가’는 서로 다른 질문이므로 필요하면 값 타입 검사까지 이어 가.

도구 선택표

원시값에는 typeof, 진짜 클래스 인스턴스에는 instanceof, 고유 속성의 존재에는 in, 리터럴 판별 필드에는 동등 비교를 써. 이 네 가지로 모자라는 복합 검증은 사용자 정의 타입 술어로 감싸면 돼.

검사하려는 실행 사실과 같은 연산자를 써. 클래스인지, 속성이 있는지, 판별값이 같은지는 서로 다른 증거야.

Code

class 엔 instanceof, 모양엔 in·typescript
// instanceof — class instance narrowing.
function stamp(x: Date | Error): string {
  if (x instanceof Date) {
    return x.toISOString();        // x: Date
  }
  return x.message;                // x: Error
}

// instanceof 가 user-defined class 와도 작동.
class NetworkError extends Error { constructor(public status: number) { super() } }
class TimeoutError extends Error { constructor(public elapsed: number) { super() } }

function handle(err: NetworkError | TimeoutError): string {
  if (err instanceof NetworkError) {
    return `HTTP ${err.status}`;   // err: NetworkError
  }
  return `Timed out after ${err.elapsed}ms`;  // err: TimeoutError
}

// `in` — property 존재 narrowing.
function printId(item: { id: number } | { name: string }) {
  if ('id' in item) {
    return item.id;                // item: { id: number }
  }
  return item.name;                // item: { name: string }
}

External links

Exercise

Date | Error | { id: number }를 문자열로 바꾸는 serialize을 작성해. 앞의 두 클래스에는 instanceof를, 평범한 객체에는 in을 사용해.
Hint
Date에서는 ISO 문자열을, Error에서는 메시지를 사용해. 남은 객체는 'id' in x를 확인한 뒤 숫자 id에 접근할 수 있어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.