Skip to content

Latest commit

 

History

History
118 lines (89 loc) · 5.28 KB

strictNullChecks.md

File metadata and controls

118 lines (89 loc) · 5.28 KB

strictNullChecks

По умолчанию null и undefined можно назначать всем типам в TypeScript, например:

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

Это спроектировано по образцу того, как многие люди пишут JavaScript. Однако, как и в других случаях, TypeScript позволяет вам явно указать, чему можно, а чему нельзя присвоить null или undefined.

В режиме strictNullChecks, значения null и undefined различаются:

let foo = undefined;
foo = null; // не Okay

Допустим, у нас есть интерфейс Member:

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

Не каждый Участник предоставит свой возраст, поэтому возраст является необязательным свойством, то есть значение age может быть или не быть undefined.

undefined - корень всех зол. Это часто приводит к ошибкам во время выполнения. Легко написать код, который будет выдавать Error во время выполнения:

getMember()
  .then(member: Member => {
    const stringifyAge = member.age.toString() // Невозможно прочитать свойство toString из undefined
  })

Но в режиме strictNullChecks эта ошибка будет обнаружена во время компиляции:

getMember()
  .then(member: Member => {
    const stringifyAge = member.age.toString() // Возможно, объект 'undefined'
  })

Оператор утверждения не-null

Новый постфиксный оператор ! может использоваться для утверждения, что его операнд не равен null и не-undefined в случаях, где средство проверки типов не может сделать логический вывод об этом. Например:

// Скомпилировано с --strictNullChecks
function validateEntity(e?: Entity) {
    // Выбрасываем исключение, если e - null или невалидный объект
}

function processEntity(e?: Entity) {
    validateEntity(e);
    let a = e.name;  // ОШИБКА TS: e может быть null.
    let b = e!.name;  // OKAY. Мы утверждаем, что e не null.
}

Обратите внимание, что это просто утверждение, и, как при утверждении типа, вы сами несете ответственность за то, чтобы значение не было null. Не-null утверждение, по сути, означает, что вы говорите компилятору: "Я знаю, что оно не null, поэтому позволь мне использовать его, как если бы оно не было null".

Оператор утверждения окончательного присваивания

TypeScript также будет жаловаться на свойства в классах, которые не инициализированы, например:

class C {
  foo: number; // OKAY, так как назначено в конструкторе
  bar: string = "hello"; // OKAY, так как есть инициализатор свойства
  baz: boolean; // ОШИБКА TS: свойство 'baz' не имеет инициализатора и не назначается напрямую в конструкторе.
  constructor() {
    this.foo = 42;
  }
}

Вы можете использовать утверждение окончательного присваивания с постфиксом к имени свойства, чтобы сообщить TypeScript, что вы инициализируете его где-нибудь, кроме конструктора, например:

class C {
  foo!: number;
  // ^
  // Обратите внимание на этот восклицательный знак!
  // Это модификатор "утверждения окончательного присваивания".
  
  constructor() {
    this.initialize();
  }
  initialize() {
    this.foo = 0;
  }
}

Вы также можете использовать это утверждение с простыми объявлениями переменных, например:

let a: number[]; // Нет утверждения
let b!: number[]; // Утвердить

initialize();

a.push(4); // TS ОШИБКА: переменная использована до присвоения
b.push(4); // OKAY: из-за утверждения

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

Как и все утверждения, вы говорите компилятору доверять вам. Компилятор не будет жаловаться, даже если код на самом деле не всегда присваивает свойство.