Шпаргалка по базовых типах TypeScript

  • 6 апреля, 17:23
  • 1731
  • 0

TypeScript - это объектно-ориентированный язык программирования, разработанный и поддерживаемый Microsoft. Это надмножество JavaScript, что означает, что любой допустимый код JavaScript также будет работать в TypeScript должным образом. Он имеет все функции JavaScript и некоторые дополнительные функции. Он должен быть скомпилирован в простой JavaScript во время выполнения, поэтому для возврата JS-кода необходим компилятор.

TypeScript использует статическую типизацию, что означает, что вы можете указать тип переменной во время объявления. И это то, что невозможно сделать с помощью JavaScript, потому что это язык с динамической типизацией, он не знает тип данных переменной, пока не присвоит значение этой переменной во время выполнения.

Статическая проверка типов делает TypeScript отличным, потому что он помогает выдавать ошибку во время компиляции, если переменная не используется или переназначена с другой аннотацией типа. Однако ошибка не блокирует выполнение кода, код JavaScript все равно будет сгенерирован.

Статическая типизация не является обязательной в TypeScript, и если тип не определен, но переменная имеет значение, TypeScript будет выводить значение как тип. А если переменная не имеет значения, по умолчанию будет установлен тип any.

Настройка TypeScript

TypeScript необходимо компилировать в простой JavaScript, поэтому нам нужно использовать инструмент для компиляции. И чтобы получить доступ к этому инструменту, вам необходимо установить TypeScript, выполнив эту команду в терминале.

  yarn add -g typescript

Или, если вы используете npm:

  npm install -g typescript

Обратите внимание, что здесь используется  -gфлаг для глобальной установки TypeScript, чтобы получить к нему доступ из любого места.

Установив TypeScript, мы получили доступ к компилятору и можем скомпилировать наш код в JavaScript. Позже мы погрузимся в это и что он делает, а пока давайте добавим файл конфигурации в наш проект. Необязательно добавлять файл конфигурации - но во многих случаях его полезно иметь, поскольку он позволяет нам определять наборы правил для компилятора.

Настройка TypeScript с помощью tsconfig

tsconfig- это файл JSON, который помогает настроить TypeScript. Лучше иметь файл конфигурации, поскольку он помогает контролировать поведение компилятора. И чтобы создать файл конфигурации, вам сначала нужно создать новый каталог с именем Pokedexи перейти в корень папки. Затем откройте его в терминале или в среде IDE и запустите эту команду, чтобы сгенерировать новый файл конфигурации TypeScript.

  tsc --init

После создания файла мы можем исследовать его в среде IDE.

  • tsconfig.json
{  "compilerOptions": {          "target": "es5",       
  "module": "commonjs",       
  "outDir": "public/js"        
  "rootDir": "src",        
  "strict": true,        
  "esModuleInterop": true        
  "forceConsistentCasingInFileNames": true  },    
"include": ["src"]
}

Теперь мы можем разбить эти значения, объяснить каждое и то, что оно делает.

  1. target: он указывает целевую версию ECMAScript при компиляции кода TypeScript. Здесь мы нацелены es5на поддержку всех браузеров, вы можете изменить это на ES6, ES3 (это значение по умолчанию, если цель не указана), ES2020 и т. Д.

  2. модуль: он определяет модуль скомпилированного кода. Модуль может быть Common JS, ES2015, ES2020 и т. Д.

  3. outDir: он указывает выходной каталог для кода, скомпилированного в JavaScript.

  4. rootDir: он определяет место, где находятся файлы TypeScript, которые необходимо скомпилировать.

  5. include: это помогает определить, какой каталог необходимо скомпилировать, потому что, если у вас нет этого значения, компилятор возьмет каждый .tsфайл и скомпилирует его в JavaScript, даже если определен выходной каталог.

Теперь мы можем погрузиться в одну из самых важных частей TypeScript: типы

Типы TypeScript

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

TypeScript имеет несколько типов, таких как number, string, boolean, enum, void, null, undefined, any, never, array и tuple. Мы расскажем не о всех типах, но имейте в виду, что они существуют.

Теперь давайте посмотрим на несколько примеров основных типов.

Основные типы TypeScript

let foo: string = "test"
let bar: number = 1
let baz: string[] = ["This", "is", "a", "Test"]

Как видите, у нас есть три переменные разных типов. fooожидает строку, barчисло и bazмассив строк. Если они получат что-либо, кроме объявленного типа, TypeScript выдаст ошибку.

Вы также можете объявить bazтак: let baz: Array<string> = ["This", "is", "a", "Test"].

Теперь давайте попробуем переназначить одну из этих переменных и посмотрим, как ведет себя TypeScript.

let foo: string = "test"
foo = 1
Type '1' is not assignable to type 'string'

TypeScript выдаст ошибку, потому что мы уже заявили, fooчто ожидаем строку как значение. И эта ошибка обнаруживается во время компиляции, что делает TypeScript очень полезным.

С TypeScript типы могут быть явными, как мы делали выше, однако они также могут быть неявными. Лучше явно определить тип данного значения, потому что это помогает компилятору и следующему разработчику, который унаследует код. Но вы также можете объявлять переменные с неявной аннотацией типа.

let foo = "test"
let bar = 1
let baz = ["This", "is", "a", "Test"]

TypeScript попытается здесь вывести как можно больше, чтобы обеспечить безопасность типов с меньшим количеством кода. Он примет значение и определит его как тип переменной. И в части ошибок ничего не изменится.

Попробуем переназначить эти переменные, чтобы посмотреть, что будет.

foo = 7
bar = "updated"
baz = [2, true, "a", 10]

TypeScript будет перехватывать ошибки, как и раньше, даже если типы переменных объявлены неявно.

Type '7' is not assignable to type 'string'.
Type '"updated"' is not assignable to type 'number'.
Type 'true' is not assignable to type 'string'.

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

Интерфейсы и псевдонимы типов

Интерфейсы и псевдонимы типов помогают определить форму объектно-подобных структур данных. По своей структуре они кажутся одинаковыми, но имейте в виду, что они разные.
Тем не менее, среди разработчиков консенсус заключается в том, чтобы использовать его interfaceвсякий раз, когда это возможно, поскольку это входит в tslintнабор правил по умолчанию .

Теперь давайте создадим интерфейс и псевдоним типа в следующем разделе, чтобы увидеть их в действии.

interface ITest {  id: number;  name?: string;
}

type TestType = {  id: number,  name?: string,
}

function myTest(args: ITest): string {  if (args.name) {    return `Hello ${args.name}`  }  return "Hello Word"
}

myTest({ id: 1 })

Как видите, структура интерфейса и псевдонима типа выглядит как объект JavaScript. Они должны определять форму данных с помощью TypeScript.

Обратите внимание, что здесь я использую необязательное поле name, добавляя вопросительный знак ( ?). Это позволяет сделать свойство nameнеобязательным. Это означает, что если значение свойства не передается name, оно будет возвращено undefinedкак значение.

Затем мы используем интерфейс ITestкак тип аргумента, полученного функцией myTest. Как и в случае с переменными, функции также могут быть определены для возврата определенного типа. И здесь возвращаемое значение должно быть строкой, иначе TypeScript выдаст ошибку.

Типы пересечений

Тип пересечения - это способ объединения нескольких типов в один. Это означает, что вы можете объединить данный тип A с типом B или более и получить один тип со всеми свойствами.

type LeftType = {  id: number  left: string
}

type RightType = {  id: number  right: string
}

type IntersectionType = LeftType & RightType

function showType(args: IntersectionType) {  console.log(args)
}

showType({ id: 1, left: "test", right: "test" })
// Output: {id: 1, left: "test", right: "test"}

Как видите, IntersectionTypeобъединяет два типа - LeftTypeи RightTypeи используйте &знак для построения типа пересечения.

Типы союзов

Типы объединения позволяют вам иметь аннотации разных типов в пределах данной переменной.

type UnionType = string | number

function showType(arg: UnionType) {  console.log(arg)
}

showType("test")
// Output: test

showType(7)
// Output: 7

Функция showTypeпредставляет собой тип объединения, который принимает в качестве параметра как строки, так и числа.

Общие типы

Универсальный тип - это способ повторного использования части данного типа. Это помогает зафиксировать тип, Tпереданный в качестве параметра.

function showType<T>(args: T) {  console.log(args)
}

showType("test")
// Output: "test"

showType(1)
// Output: 1

Чтобы создать универсальный тип, вам нужно использовать скобки и передать их Tв качестве параметра.
Здесь  используется T(название зависит от вас), а затем showTypeдважды вызываем функцию с аннотациями разных типов, потому что она универсальна - ее можно использовать повторно.

interface GenericType<T> {  id: number  name: T
}

function showType(args: GenericType<string>) {  console.log(args)
}

showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType<number>) {  console.log(args)
}

showTypeTwo({ id: 1, name: 4 })
// Output: {id: 1, name: 4}

Здесь у нас есть еще один пример с интерфейсом, GenericTypeкоторый получает универсальный тип T. И поскольку он многоразовый, мы можем вызвать его сначала строкой, а затем числом.

interface GenericType<T, U> {  id: T  name: U
}

function showType(args: GenericType<number, string>) {  console.log(args)
}

showType({ id: 1, name: "test" })
// Output: {id: 1, name: "test"}

function showTypeTwo(args: GenericType<string, string[]>) {  console.log(args)
}

showTypeTwo({ id: "001", name: ["This", "is", "a", "Test"] })
// Output: {id: "001", name: Array["This", "is", "a", "Test"]}

Универсальный тип может получать несколько аргументов. Здесь мы передаем два параметра: Tи U, а затем используем их как аннотации типов для свойств. Тем не менее, теперь мы можем использовать интерфейс и предоставлять различные типы в качестве аргументов.

Типы утилит

TypeScript предоставляет удобные встроенные утилиты, которые помогают легко управлять типами. Чтобы использовать их, вам нужно перейти <>к типу, который вы хотите преобразовать.

Partial

  • Partial<T>

Partial позволяет сделать все свойства типа Tнеобязательными. Он добавит ?отметку рядом с каждым полем.

interface PartialType {  id: number  firstName: string  lastName: string
}

function showType(args: Partial<PartialType>) {  console.log(args)
}

showType({ id: 1 })
// Output: {id: 1}

showType({ firstName: "John", lastName: "Doe" })
// Output: {firstName: "John", lastName: "Doe"}

Как видите, у нас есть интерфейс, PartialType который используется как аннотация типа для параметров, полученных функцией showType(). А чтобы сделать свойства необязательными, мы должны использовать Partialключевое слово и передать тип PartialTypeв качестве аргумента. Тем не менее, теперь все поля становятся необязательными.

Required

  • Required<T>

В отличие от этого Partial, Requiredутилита делает все свойства Tнужного типа обязательными.

interface RequiredType {  id: number  firstName?: string  lastName?: string
}

function showType(args: Required<RequiredType>) {  console.log(args)
}

showType({ id: 1, firstName: "John", lastName: "Doe" })
// Output: { id: 1, firstName: "John", lastName: "Doe" }

showType({ id: 1 })
// Error: Type '{ id: number: }' is missing the following properties from type 'Required<RequiredType>': firstName, lastName

RequiredУтилита сделает все свойства требуется , даже если мы их необязательными перед использованием утилиты. А если свойство не указано, TypeScript выдаст ошибку.

Readonly

  • Readonly<T>

Этот тип утилит преобразует все свойства типа T, чтобы сделать их не переназначаемыми с новым значением.

interface ReadonlyType {  id: number  name: string
}

function showType(args: Readonly<ReadonlyType>) {  args.id = 4  console.log(args)
}

showType({ id: 1, name: "Doe" })
// Error: Cannot assign to 'id' because it is a read-only property.

Здесь мы используем утилиту, Readonlyчтобы сделать свойства ReadonlyTypeне переназначаемыми. Тем не менее, если вы попытаетесь дать новое значение одному из этих полей, будет выдана ошибка.

Кроме того, вы также можете использовать ключевое слово readonlyперед свойством, чтобы его нельзя было переназначить.

interface ReadonlyType {  
readonly id: number  name: string
}

Pick

  • Pick<T, K>

Это позволяет вам создать новый тип из существующей модели T, выбрав некоторые свойства Kэтого типа.

interface PickType {  id: number  firstName: string  lastName: string
}

function showType(args: Pick<PickType, "firstName" | "lastName">) {  console.log(args)
}

showType({ firstName: "John", lastName: "Doe" })
// Output: {firstName: "John"}

showType({ id: 3 })
// Error: Object literal may only specify known properties, and 'id' does not exist in type 'Pick<PickType, "firstName" | "lastName">'

Pickнемного отличается от предыдущих, которые мы уже видели. Он ожидает двух параметров - Tэто тип, из которого вы хотите выбрать элементы, и Kсвойство, которое вы хотите выбрать. Вы также можете выбрать несколько полей, разделив их |символом вертикальной черты ( ).

Omit

  • Omit<T, K>

OmitУтилита противоположность Pick типа. И вместо выбора элементов он удалит Kсвойства из типа T.

interface PickType {  id: number  firstName: string  lastName: string
}

function showType(args: Omit<PickType, "firstName" | "lastName">) {  console.log(args)
}

showType({ id: 7 })
// Output: {id: 7}

showType({ firstName: "John" })
// Error: Object literal may only specify known properties, and 'firstName' does not exist in type 'Pick<PickType, "id">'

Эта утилита аналогична принципу Pickработы. Ожидается, что тип и свойства будут исключены из этого типа.

Extract

  • Extract<T, U>

Extractпозволяет вам создать тип, выбирая свойства, которые представлены в двух разных типах. Утилита извлечет из Tвсех свойств, которым можно присвоить U.

interface FirstType {  id: number  firstName: string  lastName: string
}

interface SecondType {  id: number  address: string  city: string
}

type ExtractType = Extract<keyof FirstType, keyof SecondType>
// Output: "id"

Здесь у нас есть два типа, которые имеют общее свойство id. И, следовательно, используя Extractключевое слово, мы возвращаем поле, idпоскольку оно присутствует в обоих интерфейсах. А если у вас несколько общих полей, утилита извлечет все похожие свойства.

Exclude

В отличие от этого Extract, Excludeутилита будет создавать тип, исключая свойства, которые уже присутствуют в двух разных типах. Он исключается из Tвсех полей, которым можно присвоить U.

interface FirstType {  id: number  firstName: string  lastName: string
}

interface SecondType {  id: number  address: string  city: string
}

type ExcludeType = Exclude<keyof FirstType, keyof SecondType>

// Output; "firstName" | "lastName"

Как вы можете видеть здесь, свойства firstNameи lastNameприсваиваются SecondTypeтипу, поскольку их там нет. И, используя Extractключевое слово, мы возвращаем эти поля, как и ожидалось.

Record

  • Record<K,T>

Эта утилита помогает вам создать тип с набором свойств Kданного типа T. Recordдействительно удобно использовать, когда дело доходит до сопоставления свойств одного типа с другим.

interface EmployeeType {  id: number  fullname: string  role: string
}

let employees: Record<number, EmployeeType> = {  0: { id: 1, fullname: "John Doe", role: "Designer" },  1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },  2: { id: 3, fullname: "Sara Duckson", role: "Developer" },
}

// 0: { id: 1, fullname: "John Doe", role: "Designer" },
// 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
// 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }

Способ Recordработы относительно прост. Здесь он ожидает a numberв качестве типа, поэтому у нас есть 0, 1 и 2 в качестве ключей для employeesпеременной. И если вы попытаетесь использовать строку как свойство, будет выдана ошибка. Затем набор свойств задается EmployeeTypeобъектом с полями id, fullName и role.

NonNullable

  • NonNullable<T>

Он позволяет снимать nullи undefinedс типа T.

type NonNullableType = string | number | null | undefined

function showType(args: NonNullable<NonNullableType>) {  console.log(args)
}

showType("test")
// Output: "test"

showType(1)
// Output: 1

showType(null)
// Error: Argument of type 'null' is not assignable to parameter of type 'string | number'.

showType(undefined)
// Error: Argument of type 'undefined' is not assignable to parameter of type 'string | number'.

Здесь мы передаем тип NonNullableTypeв качестве аргумента NonNullableутилите, которая создает новый тип путем исключения nullи undefinedиз этого типа. Тем не менее, если вы передадите значение, допускающее значение NULL, TypeScript выдаст ошибку.

Кстати, если вы добавите --strictNullChecksфлаг в tsconfigфайл, TypeScript применит правила, не допускающие обнуления.

Mapped types

Сопоставленные типы позволяют вам взять существующую модель и преобразовать каждое из ее свойств в новый тип. Обратите внимание, что некоторые типы утилит, рассмотренные ранее, также являются отображаемыми типами.

type StringMap<T> = {  [P in keyof T]: string
}

function showType(arg: StringMap<{ id: number; name: string }>) {  console.log(arg)
}

showType({ id: 1, name: "Test" })
// Error: Type 'number' is not assignable to type 'string'.

showType({ id: "testId", name: "This is a Test" })
// Output: {id: "testId", name: "This is a Test"}

StringMap<>преобразует любые переданные типы в строку. Тем не менее, если мы используем его в функции showType(), полученные параметры должны быть строкой, иначе TypeScript выдаст ошибку.

Type Guards

Type Guards позволяет вам проверять тип переменной или объекта с помощью оператора. Это условный блок , который возвращает тип использования typeof, instanceofили in.

  • typeof
function showType(x: number | string) {  if (typeof x === "number") {    return `The result is ${x + x}`  }  throw new Error(`This operation can't be done on a ${typeof x}`)
}

showType("I'm not a number")
// Error: This operation can't be done on a string

showType(7)
// Output: The result is 14

Как видите, у нас есть обычный условный блок JavaScript, который проверяет тип аргумента, полученного с помощью typeof. Теперь вы можете защитить свой тип с помощью этого условия.

  • instanceof
class Foo {  bar() {    return "Hello World"  }
}

class Bar {  baz = "123"
}

function showType(arg: Foo | Bar) {  if (arg instanceof Foo) {    console.log(arg.bar())    return arg.bar()  }
  throw new Error("The type is not supported")
}

showType(new Foo())
// Output: Hello World

showType(new Bar())
// Error: The type is not supported

Как и в предыдущем примере, этот также является защитником типа, который проверяет, является ли полученный параметр частью Fooкласса, и обрабатывает его соответственно.

  • in
interface FirstType {  x: number
}
interface SecondType {  y: string
}

function showType(arg: FirstType | SecondType) {  if ("x" in arg) {    console.log(`The property ${arg.x} exists`)    return `The property ${arg.x} exists`  }  throw new Error("This type is not expected")
}

showType({ x: 7 })
// Output: The property 7 exists

showType({ y: "ccc" })
// Error: This type is not expected

inОператор позволяет проверить , является ли это свойство xсуществует или нет на объекте , полученный в качестве параметра.

Conditional Types

Он тестирует два типа и выбирает один из них в зависимости от результата этого теста.

type NonNullable<T> = T extends null | undefined ? never : T

Этот пример NonNullableслужебного типа проверяет, является ли тип нулевым или нет, и обрабатывает его в зависимости от этого. И, как вы можете заметить, он использует тернарный оператор JavaScript.


0 комментариев
Сортировка:
Добавить комментарий

IT Новости