Typescript: Классы как типы
Классы в TypeScript являются одновременно значением и типом данных. Второе особенно важно в контексте типизации функций и методов, что мы и изучим в этом уроке.
Рассмотрим следующий пример:
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
function isEqual(p1: Point, p2: Point): boolean {
return p1.x === p2.x && p1.y === p2.y;
}Здесь функция isEqual() принимает два аргумента типа Point. И хоть мы используем в качестве типа класс Point, но передавать в функции мы можем любые объекты с полями x и y:
isEqual({ x: 1, y: 2 }, { x: 1, y: 2 }); // trueТакое поведение обусловлено структурной типизацией. При сравнении типов TypeScript сравнивает их структуру, а не имена. На практике это упрощает работу с внешними библиотеками и заглушками для тестирования.
TypeScript будет явно требовать экземпляр класса, если у него есть приватные поля:
class Point {
private x: number;
private y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
isEqual(p2: Point): boolean {
return this.x === p2.x && this.y === p2.y;
}
}
const point = new Point(1, 2);
point.isEqual(new Point(1, 2)); // true
point.isEqual({ x: 1, y: 2 }); // Error: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type 'Point'.Задание
Реализуйте класс CustomFile, в конструктор которого передается объект с именем файла и размером в байтах или другой файл. Как и в прошлом уроке, name и size остаются публичными полями и доступны снаружи, а вот признак копии наружу отдавать не нужно — храните его в приватном поле.
Внутри класса определите метод toString(), который должен вернуть форматированную строку в формате (copy) <file-name> (<size> bytes). (copy) должно выводиться только в том случае, если файл является копией другого файла.
const file = new CustomFile({ name: "open-world.jpeg", size: 1000 });
console.log(file.toString()); // open-world.jpeg (1000 bytes)
const file2 = new CustomFile(file);
console.log(file2.toString()); // (copy) open-world.jpeg (1000 bytes)
const file3 = new CustomFile(file2);
console.log(file2.toString()); // (copy) open-world.jpeg (1000 bytes)Полезное
Typescript: Классы как типы
Классы в TypeScript являются одновременно значением и типом данных. Второе особенно важно в контексте типизации функций и методов, что мы и изучим в этом уроке.
Рассмотрим следующий пример:
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
function isEqual(p1: Point, p2: Point): boolean {
return p1.x === p2.x && p1.y === p2.y;
}Здесь функция isEqual() принимает два аргумента типа Point. И хоть мы используем в качестве типа класс Point, но передавать в функции мы можем любые объекты с полями x и y:
isEqual({ x: 1, y: 2 }, { x: 1, y: 2 }); // trueТакое поведение обусловлено структурной типизацией. При сравнении типов TypeScript сравнивает их структуру, а не имена. На практике это упрощает работу с внешними библиотеками и заглушками для тестирования.
TypeScript будет явно требовать экземпляр класса, если у него есть приватные поля:
class Point {
private x: number;
private y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
isEqual(p2: Point): boolean {
return this.x === p2.x && this.y === p2.y;
}
}
const point = new Point(1, 2);
point.isEqual(new Point(1, 2)); // true
point.isEqual({ x: 1, y: 2 }); // Error: Argument of type '{ x: number; y: number; }' is not assignable to parameter of type 'Point'.Задание
Реализуйте класс CustomFile, в конструктор которого передается объект с именем файла и размером в байтах или другой файл. Как и в прошлом уроке, name и size остаются публичными полями и доступны снаружи, а вот признак копии наружу отдавать не нужно — храните его в приватном поле.
Внутри класса определите метод toString(), который должен вернуть форматированную строку в формате (copy) <file-name> (<size> bytes). (copy) должно выводиться только в том случае, если файл является копией другого файла.
const file = new CustomFile({ name: "open-world.jpeg", size: 1000 });
console.log(file.toString()); // open-world.jpeg (1000 bytes)
const file2 = new CustomFile(file);
console.log(file2.toString()); // (copy) open-world.jpeg (1000 bytes)
const file3 = new CustomFile(file2);
console.log(file2.toString()); // (copy) open-world.jpeg (1000 bytes)Полезное
Ваше упражнение проверяется по этим тестам
import { expect, test } from "vitest";
import CustomFile from "./index";
test("CustomFile", () => {
const file = new CustomFile({ name: "foo.txt", size: 4000 });
expect(file.name).toBe("foo.txt");
expect(file.size).toBe(4000);
expect(file.toString()).toBe("foo.txt (4000 bytes)");
const file2 = new CustomFile(file);
expect(file2.toString()).toBe("(copy) foo.txt (4000 bytes)");
});Решение учителя откроется через:
20:00
