Перейти к содержанию

Ленивая инициализация объекта

Довольно часто в JavaScript вы инициализируете объекты следующим образом:

1
2
3
let foo = {};
foo.bar = 123;
foo.bas = 'Hello World';

Как только вы переведёте код в TypeScript, вы начнете получать следующие ошибки:

1
2
3
let foo = {};
foo.bar = 123; // Ошибка: свойство 'bar' не существует для типа '{}'
foo.bas = 'Hello World'; // Ошибка: свойство 'bas' не существует для типа '{}'

Это потому, что из структуры let foo = {} TypeScript логически выводит тип foo (левая часть инициализирующего присваивания) как тип правой части {}(т.е. объект без свойств). Поэтому произойдёт ошибка, если вы попытаетесь присвоить значение свойству, о котором компилятор не знает.

Идеальное решение

Правильный способ инициализировать объект в TypeScript - сделать это в присвоении:

1
2
3
4
let foo = {
    bar: 123,
    bas: 'Hello World',
};

Это также отлично подходит для ревью и удобства сопровождения кода.

Паттерны быстрого решения и компромиссной ленивой инициализации, описанные ниже, страдают от забывания инициализировать свойство.

Быстрое решение

Если у вас есть большая кодовая база на JavaScript, которую вы переносите на TypeScript, идеальное решение может оказаться для вас нецелесообразным. В этом случае вы можете осторожно использовать утверждение типа, чтобы заставить компилятор замолчать:

1
2
3
let foo = {} as any;
foo.bar = 123;
foo.bas = 'Hello World';

Компромиссное решение

Конечно, использование утверждения any может быть очень плохим решением, поскольку оно подрывает безопасность TypeScript. Компромиссное решение - создать интерфейс, чтобы гарантировать:

  • Хорошее описание
  • Безопасное присвоение

Это показано ниже:

1
2
3
4
5
6
7
8
interface Foo {
    bar: number;
    bas: string;
}

let foo = {} as Foo;
foo.bar = 123;
foo.bas = 'Hello World';

Вот краткий пример, показывающий, что использование интерфейса может вам помочь:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
interface Foo {
    bar: number;
    bas: string;
}

let foo = {} as Foo;
foo.bar = 123;
foo.bas = 'Hello World';

// позже в кодовой базе:
foo.bar = 'Hello Stranger'; // Ошибка: вы, вероятно, опечатались `bas`
// вместо `bar`, не возможно присвоить строку числу

Комментарии