Typescript: Статические методы и свойства

Иногда нам требуется задать свойство или метод, который будет общим для всех экземпляров этого класса. Например, чтобы определить, является ли объект экземпляром класса. В таком случае при объявлении метода мы можем указать ключевое слово static, и он станет доступен через имя класса:

class CustomFile {
  private static readonly maxCustomFileSize = 1000;

  static isCustomFile(file: CustomFile): boolean {
    return file instanceof CustomFile;
  }

  protected static isCustomFileTooBig(size: number): boolean {
    return size > CustomFile.maxCustomFileSize;
  }

  constructor(private name: string, private size: number) {
    if (CustomFile.isCustomFileTooBig(size)) {
      throw new Error('CustomFile is too big');
    }
  }
}

CustomFile.isCustomFile(new CustomFile('open-world.jpeg', 1000)); // true

Статическим методам и свойствам также можно назначить модификаторы доступа public, protected и private и модификатор неизменяемости readonly. Это позволяет ограничить использование свойств и методов только текущим классом или наследниками.

В отличии от JavaScript в TypeScript статические свойства и методы не могут быть переопределены в подклассах:

class CustomFile {
  static maxCustomFileSize = 1000;

  static isCustomFile(file: CustomFile): boolean {
    return file instanceof CustomFile;
  }
}

class ImageCustomFile extends CustomFile {
  static maxCustomFileSize = 2000; // Error!

  static isCustomFile(file: CustomFile): boolean { // Error!
    return file instanceof ImageCustomFile;
  }
}

Такой код не удастся скомпилировать. При этом остается доступ к статическим свойствам и методам родительского класса:

const file = new ImageCustomFile();
console.log(ImageCustomFile.maxCustomFileSize); // 1000
console.log(ImageCustomFile.isCustomFile(file)); // true

Задание

Другое полезное применение статических свойств и методов — создание фабричных методов. Фабричный метод — это статический метод, который возвращает новый экземпляр класса. Реализуйте класс UserResponse с полем user: string и фабричный метод fromArray, который принимает массив и возвращает массив экземпляров класса UserResponse:

const response = UserResponse.fromArray(['user1', 'user2', 'user3']);
console.log(response[0].user); // user1
console.log(response[0] instanceof UserResponse); // true
Упражнение не проходит проверку — что делать? 😶

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя 🤔

Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно 🙄

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

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

Нашли ошибку? Есть что добавить? Пулреквесты приветствуются
Loading...

Ваше упражнение проверяется по этим тестам

1import UserResponse from './index';
2
3test('UserResponse', () => {
4  const users = ['user1', 'user2'];
5  const result = UserResponse.fromArray(users);
6
7  expect(result).toEqual([
8    new UserResponse('user1'),
9    new UserResponse('user2'),
10  ]);
11  expect(result[0]).toBeInstanceOf(UserResponse);
12
13  const users2 = ['user3', 'user4', 'user5'];
14  const result2 = UserResponse.fromArray(users2);
15
16  expect(result2[0].user).toBe('user3');
17  expect(result2[2]).toBeInstanceOf(UserResponse);
18});
19

Решение учителя откроется через:

20:00
waiting_clock