Представим программу, в которой есть объект пользователя. Этот объект используется повсеместно. В такой ситуации описание типа этого объекта будет повторяться в каждом определении функции:
function doSomething(user: { firstName: string, lastName: number }) {}
function doSomethingElse(user: { firstName: string, lastName: number }) {}
function doSomethingAnother(user: { firstName: string, lastName: number }) {}
Во-первых, здесь много дублирования. Во-вторых, значительно усложняется изменение структуры, так как придется руками править все места, где встречается это определение. В этом уроке разберем, как избежать таких проблем.
Чтобы не делать одну и ту же работу, TypeScript позволяет задавать псевдоним для составных типов. Так мы не будем повторяться:
type User = {
firstName: string;
pointsCount: number;
}
Теперь можно провести замену во всех функциях:
function doSomething(user: User) {
// ...
}
Псевдоним — это не создание нового типа данных. Это способ сокращенно записать определение типа. Поэтому следующие примеры будут работать без проблем:
const user = {
firstName: 'Mike',
pointsCount: 1000,
};
// Оба вызова работают
doSomething(user);
doSomething({ firstName: 'Bob', pointsCount: 1800 });
При этом разработчики на TypeScript говорят «создал тип», а не «создал псевдоним типа». Поэтому в этом курсе мы будем придерживаться общепринятого формата.
Типы можно задавать для любых типов данных, например, для простых:
type SomeType = string;
А также для составных:
// union тип из трех возможных значений
type SomeType = string | number | null;
// Функция
type Countable = (coll: number[]) => number
Описание типа функции вне объекта и внутри отличается. Когда функция записывается самостоятельно, используется формат стрелочной функции:
type Countable = (coll: number[]) => number
Внутри типа, который описывает объект, формат меняется на используемый для обычных свойств:
type User = {
firstName: string;
pointsCount: number;
count(coll: number[]): number;
}
Но это не касается колбеков, которые могут быть использованы внутри:
type User = {
firstName: string;
pointsCount: number;
// Типы взяты для примера
count(coll: (v: string) => string): number;
}
В этом уроке мы научились использовать псевдонимы типов. Также мы узнали, как задавать псевдоним для составных типов.
Реализуйте функцию getOlderUser()
, которая принимает на вход двух пользователей и возвращает того, который старше. Если пользователи являются ровесниками, то возвращается null
:
const user1 = { name: 'Petr', age: 8 };
Определите для пользователя псевдоним, чтобы не дублировать определение его типа в параметрах функции.
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1import * as ta from 'type-assertions';
2
3import getOlderUser, { User } from './index';
4
5test('function', () => {
6 const user1 = {
7 name: 'sem',
8 age: 3,
9 };
10
11 const user2 = {
12 name: 'inna',
13 age: 5,
14 };
15
16 const user3 = {
17 name: 'mika',
18 age: 5,
19 };
20
21 expect(getOlderUser(user1, user2)).toEqual(user2);
22 expect(getOlderUser(user2, user1)).toEqual(user2);
23
24 expect(getOlderUser(user2, user3)).toBeNull();
25
26 ta.assert<ta.Equal<ReturnType<typeof getOlderUser>, User | null>>();
27});
28
Решение учителя откроется через: