Typescript 유형 어설션

유형 어설션은 if 문에 포함될 필요가 없다는 점을 제외하고는 의 와 매우 유사합니다.

블로그가 있고 인증된 사용자가 댓글을 게시할 수 있다고 상상해 보십시오. 우리는 다음과 같은 기능을 생각해냅니다.

function isAuthenticated(user: User | null) {
  return typeof user !== null;
}

function addComment(user: User | null, comment: string) {
  if (!isAuthenticated(user)) {
    throw new Error('unauthenticated')
  }

  db.comments.insert({ author: user._id, comment });
}


사용자가 로그인했는지 알려주는 isAuthenticated 도우미를 추출했습니다. 그리고 로그인하지 않은 경우 오류를 발생시킵니다.

순수한 JavaScript에서는 지금쯤이면 완료될 것입니다. usernull 이면 오류가 발생하므로 데이터베이스 문에 도달할 때까지 user 개체가 정의되어 있다고 확신합니다.

반면에 TypeScript는 여전히 userUser | null로 봅니다. 이를 해결하기 위해 타입 가드를 도입할 수 있습니다. 유형 술어 user is User 를 추가하여 도우미를 업데이트하면 사용자가 null 문의 범위에 if 있으므로 그 뒤에 User 있어야 함을 이해합니다.

function isAuthenticated(user: User | null): user is User {
  return typeof user !== null;
}


익숙하지 않은 경우 이전 기사를 읽는 것이 좋습니다.

유형 술어를 추가하여 데이터베이스 문의 문제를 해결했습니다. TypeScript는 해당 단계에서 usernull 절대 아님을 알고 있습니다.

어설션 함수



문제는 반복에 있습니다. 프로젝트 전체에 3줄의 코드가 있으면 노이즈가 추가됩니다. 게다가 이것이 정의한 유일한 검사일 가능성은 거의 없습니다.

이 수표를 다음과 같이 바꿀 수 있습니다.

function assertAuthenticated(user: User | null): user is User {
  if (user === null || user === undefined) {
    throw new Error('unauthenticated');
  }

  return true;
}

function addComment(user: User | null, comment: string) {
  assertAuthenticated(user);

  db.comments.insert({ author: user._id, comment });
}


일반 JavaScript에서는 여전히 작동합니다. assertAuthenticated 함수는 user 개체가 정의되지 않은 경우 throw되고 오류가 전파되기 때문에 데이터베이스 문에 도달하지 않습니다.

그러나 랩핑if 문을 제거했기 때문에 TypeScript는 다시 만족하지 않습니다. 데이터베이스 문의 user._idTS2531: Object is possibly 'null'를 발생시킵니다. 이를 수정하기 위해 Type assertion 을 삽입합니다.

정말 사소한 일입니다. 형식 술어 앞에 asserts를 추가하고 어설션 함수에서 return 문을 제거하기만 하면 됩니다. 유형 가드가 boolean 를 반환해야 하는 경우 어설션 함수는 void 를 반환해야 합니다.

function assertAuthenticated(user: User | null): asserts user is User {
  if (user === null || user === undefined) {
    throw new Error('unauthenticated');
  }
}


이제 이 함수를 호출할 때 TypeScript는 user의 값이 해당 줄 뒤에 null가 될 수 없다는 것을 알고 있습니다.

function addComment(user: User | null, comment: string) {
  assertAuthenticated(user);
  db.comments.insert({ author: user._id, comment });
}


일반 주장



이제 asserts 에 대해 알았으므로 재사용 가능한 도우미 함수를 아주 쉽게 도입할 수도 있습니다.

function assert<T>(
  condition: T,
  message,
): asserts condition is Exclude<T, null | undefined> {
  if (condition === null || condition === undefined) {
    throw new Error(message);
  }
}


그런 다음 선택적 또는 부분 값을 허용하는 함수가 있을 때마다 thisassert 도우미를 사용하여 간단히 보호할 수 있습니다.

async function latestBlog() {
  const blog = await db.blogs.findOne({ author: 'smeijer' }); // Blog | null
  assert(blog, 'author does  not have any blogs');

  // and here we know `blog: Blog`
}

blog가 데이터베이스에서 발견되지 않으면 assert 문은 체인 위로 오류를 던질 것입니다. 무언가를 찾았다면 assert 호출 후에 안전하게 객체로 작업할 수 있습니다.

다음에 as MyType 를 사용하여 속성을 유형 변환하는 것을 고려할 때 대신 유형 어설션을 작성하는 것을 고려하십시오. 단순히 TypeScript를 침묵시키는 대신, 한 줄의 코드로 런타임 유효성 검사를 받을 수 있습니다.


👋 저는 스테판이고 짓고 있어요 metricmouse.com . 제 글을 더 읽고 싶으시면 저를 팔로우하세요.

좋은 웹페이지 즐겨찾기