В этом блоге мы подробно рассмотрим некоторые из более продвинутых встроенных типов, включенных в TypeScript. Если вы новичок в TypeScript, я рекомендую начать с некоторых из моих блогов по обучению новичков:
-
TypeScript: Руководство по легкому старту
-
TypeScript: Основные типы.
Псевдонимы типов
В нашем последнем уроке мы создали этот объект TypeScript:
let contactInfo: {
name: string,
phone: number,
fax?: number
} = {name: 'Vincent', phone: 123_456_7890}
Это замечательно, но это создает несколько проблем для нас:
1. Если мы захотим создать новый объект контактной информации, нам придется повторить эту структуру:
2. Другой объект контактной информации может иметь другие свойства, поэтому его форма может меняться.
3. Общая структура может быть трудно интерпретируемой с первого взгляда.
Именно здесь на помощь приходят псевдонимы типов для создания пользовательских типов. Для этого введите ключевое слово ‘type’, за которым следует имя объекта в регистре Паскаля (первая буква в каждом слове прописная), как показано ниже:
type ContactInfo = {
name: string,
phone: number,
fax?: number,
}
Теперь, когда структура определена в нашем псевдониме, мы можем удалить ее из нашего предыдущего объекта и создать новый объект с нашей новой пользовательской типизацией:
let myContactInfo: ContactInfo = {
name: "Vincent",
phone: 123_456_7890,
}
Союзы
Союзы — это довольно простая концепция. Вы можете использовать их для придания дополнительных типов переменным или параметрам функций. Это делается с помощью символа «|»:
function addTwo(num: number | string): number{
return num + 2;
}
Разбирая эту функцию на части, можно сказать, что она принимает один аргумент, который может быть либо числом, либо строкой. Хотя приведенная выше функция может принимать любой из них, существует вероятность того, что она не вернет число, как требуется (когда вы добавляете строку к числу, результатом будет строка).
Примечание: В предыдущем блоге мы говорили о завершении кода и о том, что это одно из преимуществ, которые предоставляет нам TypeScript. Однако, когда мы используем союзы, как в этом примере, единственными методами, которые мы сможем увидеть, будут методы, общие для строк и чисел:
Поэтому внутри нашей функции мы можем добавить немного условной логики, чтобы прояснить ситуацию:
function addTwo(num: number | string): number{
if (typeof num === "number") {
return num + 2;
} else {
return parseInt(num) + 2;
}
}
Этот процесс использования условной логики для выяснения типа аргумента известен как сужение типа.
И теперь с помощью умозаключения TypeScript узнает, что num в первом условии будет числовым типом, а num в условии ‘else’ должен быть строкой, и поэтому соответствующие методы типов снова станут доступны при завершении кода.
Пересечения
Концепция типов пересечений аналогична союзам. Однако вместо того, чтобы позволить передаваемому значению быть одним типом ИЛИ другим, она позволяет переменной быть обоими типами одновременно. Наш предыдущий пример не лучший способ показать это, так как объект не может быть одновременно числом и строкой, но давайте попробуем это сделать с некоторыми пользовательскими типами.
Представьте, что мы создаем простые объекты видеоигры.
Для некоторых сущностей мы хотим, чтобы они могли двигаться только влево или вправо, как гумба в играх Mario!
Обратите внимание, что это не обязательно то, как были закодированы реальные сущности видеоигр, это просто визуальная аналогия.
Для других мы можем захотеть, чтобы они могли двигаться вверх и вниз, как растение пиранья.
Наши пользовательские типы могут выглядеть примерно так:
type LeftAndRight = {
moveLeft: () => <...>,
moveRight: () => <...>
}
type UpAndDown = {
moveUp: () => <...>,
moveDown:() => <...>
}
Но что, если мы хотим получить объект, который может двигаться и влево, и вправо, и вверх, и вниз, как летающий копа-трупа.
Чтобы создать пользовательский тип, который будет иметь атрибуты уже существующих или созданных нами типов, мы можем использовать символ ‘&’, как показано ниже:
type UpDownLeftAndRight = LeftAndRight & UpAndDown;
// and now we can create a variable of that combined type
let flyingKoopaTroopa: UpDownLeftAndRight = {
moveLeft: () => <...>,
moveRight: () => <...>,
moveUp: () => <...>,
moveDown: () => <...>,
}
Буквальные типы
Мы узнали, что в TypeScript мы можем назначать переменные определенным типам данных, например строкам. Но мы также можем указать конкретные строки, присвоив ‘type’ конкретной строке, как показано ниже:
type CoinFlip = 'heads' | 'tails';
//here we are creating a custom type that can only be of two values
let firstFlip: CoinFlip = 'heads'; //this is ok
let secondFlip: CoinFlip = 'tails'; //this is also ok
let thirdFlip: CoinFlip = 'a crow took it'; //this is not ok
Типы с нулевым значением
По умолчанию конфигурация TypeScripts не позволяет использовать нулевые типы при присвоении переменных определенным типам. Однако, если вы хотите разрешить переменной быть нулевой, вы можете указать ее с помощью оператора объединения:
let greeting: string | null
//we are saying that greeting can be either a string or null
greeting = null // this is ok
greeting = 'Hello!' // this is also ok
greeting = undefined // error
// if you wish to also specify that greeting can also be undefined, you would need to add another union to include 'undefined' types
Поздравляем, теперь вы эксперт по типам TypeScript! Надеюсь, эта статья была информативной и сэкономит вам много времени на отладку в будущем.