Иногда нам требуется задать свойство или метод, который будет общим для всех экземпляров этого класса. Например, чтобы определить, является ли объект экземпляром класса. В таком случае при объявлении метода мы можем указать ключевое слово 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
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
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
Решение учителя откроется через: