TypeScript Deep Dive
  • README
  • 시작하기
    • 왜 타입스크립트인가
  • 자바스크립트
    • 비교 연산자
    • 참조 연산자
    • Null vs. Undefined
    • this
    • 클로저
    • Number
    • Truthy
  • 미래의 자바스크립트
    • 클래스
      • 즉시실행함수
    • 화살표 함수
    • 나머지 연산자
    • let
    • const
    • 비구조화 할당
    • 전개 연산자
    • for...of
    • 이터레이터
    • 템플릿 리터럴
    • 프로미스
    • 제네레이터
    • Async Await
  • 프로젝트
    • 컴파일러 제어
      • tsconfig.json
      • 파일 경로 지정
    • 선언
    • 모듈화
      • 파일을 이용한 모듈화
      • globals.d.ts
    • 네임스페이스
    • 동적 표현식 가져오기
  • Node.js 시작하기
  • Browser 시작하기
  • 타입스크립트 타입 시스템
    • 자바스크립트 마이그레이션 가이드
    • @types
    • 주변 선언
      • 파일 선언
      • 변수
    • 인터페이스
    • 열거형(Enums)
    • lib.d.ts
    • 함수
    • 콜러블(Callable)
    • 타입 표명(Type Assertion)
    • 신선도(Freshness)
    • 타입 가드
    • 리터럴(Literal)
    • 읽기 전용(readonly)
    • 제네릭
    • 타입 인터페이스
    • 타입 호환성
    • Never 타입
    • 구별된 유니온
    • 인덱스 서명(Index Signature)
    • 타입 이동하기
    • 예외 처리
    • 믹스인(Mixin)
  • JSX
    • React
    • Non React JSX
  • Options
    • noImplicitAny
    • strictNullChecks
  • 타입스크립트 에러
    • 에러 메세지
    • 공통 에러
  • NPM
  • 테스트
    • Jest
    • Cypress
  • Tools
    • Prettier
    • Husky
    • ESLint
    • Changelog
  • 팁
    • 문자열 Enums
    • 타입 단언
    • 상태 저장 함수
    • 커링
    • 제네릭 타입 예시
    • 객체 타입 설정
    • 유용한 클래스
    • Import / Export
    • 속성 Setters
    • outFile 주의사항
    • 제이쿼리 팁
    • 정적 생성자
    • 싱글톤 패턴
    • 함수 파라미터
    • 토글 생성
    • Import 여러개 하기
    • 배열 생성
    • 생성자에서 타입정의
  • 스타일 가이드
  • 타입스크립트 컴파일러 구조
    • Program
    • AST
      • TIP: Visit Children
      • TIP: SyntaxKind enum
      • Trivia
    • Scanner
    • Parser
      • Parser Functions
    • Binder
      • Binder Functions
      • Binder Declarations
      • Binder Container
      • Binder SymbolTable
      • Binder Error Reporting
    • Checker
      • Checker Diagnostics
      • Checker Error Reporting
    • Emitter
      • Emitter Functions
      • Emitter SourceMaps
    • Contributing
Powered by GitBook
On this page
  • Non-Null Assertion Operator
  • Definite Assignment Assertion Operator

Was this helpful?

  1. Options

strictNullChecks

By default null and undefined are assignable to all types in TypeScript e.g.

let foo: number = 123;
foo = null; // Okay
foo = undefined; // Okay

This is modelled after how a lot of people write JavaScript. However, like all things, TypeScript allows you to be explicit about what can and cannot be assigned a null or undefined.

In strict null checking mode, null and undefined are different:

let foo = undefined;
foo = null; // NOT Okay

Let's say we have a Member interface:

interface Member {
  name: string,
  age?: number
}

Not every Member will provide their age, so age is an optional property, meaning the value of age may or may not be undefined.

undefined is the root of all evil. It often leads to runtime errors. It is easy to write code that will throw Error at runtime:

getMember()
  .then(member: Member => {
    const stringifyAge = member.age.toString() // Cannot read property 'toString' of undefined
  })

But in strict null checking mode, this error will be caught at compile time:

getMember()
  .then(member: Member => {
    const stringifyAge = member.age.toString() // Object is possibly 'undefined'
  })

Non-Null Assertion Operator

A new ! post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. For example:

// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
    // Throw exception if e is null or invalid entity
}

function processEntity(e?: Entity) {
    validateEntity(e);
    let a = e.name;  // TS ERROR: e may be null.
    let b = e!.name;  // OKAY. We are asserting that e is non-null.
}

Note that it is just an assertion, and just like type assertions you are responsible for making sure the value is not null. A non-null assertion is essentially you telling the compiler "I know it's not null so let me use it as though it's not null".

Definite Assignment Assertion Operator

TypeScript will also complain about properties in classes not being initialized e.g.:

class C {
  foo: number; // OKAY as assigned in constructor
  bar: string = "hello"; // OKAY as has property initializer
  baz: boolean; // TS ERROR: Property 'baz' has no initializer and is not assigned directly in the constructor.
  constructor() {
    this.foo = 42;
  }
}

You can use the definite assignment assertion postfixed to the property name to tell TypeScript that you are initializing it somewhere other than the constructor e.g.

class C {
  foo!: number;
  // ^
  // Notice this exclamation point!
  // This is the "definite assignment assertion" modifier.

  constructor() {
    this.initialize();
  }
  initialize() {
    this.foo = 0;
  }
}

You can also use this assertion with simple variable declarations e.g.:

let a: number[]; // No assertion
let b!: number[]; // Assert

initialize();

a.push(4); // TS ERROR: variable used before assignment
b.push(4); // OKAY: because of the assertion

function initialize() {
  a = [0, 1, 2, 3];
  b = [0, 1, 2, 3];
}

Like all assertions, you are telling the compiler to trust you. The compiler will not complain even if the code doesn't actually always assign the property.

PreviousnoImplicitAnyNext타입스크립트 에러

Last updated 6 years ago

Was this helpful?