Pull to refresh

JavaScript vs TypeScript. Почему Вы должны изучить TypeScript?

Reading time7 min
Views33K
Original author: hiro9108

Что такое TypeScript?

JavaScript один из самый популярных языков программирования. Одна из причин этого, что он является динамически типизированным. Другим словами, JavaScript – это более свободный язык, но, если вы встретите много кода в вашем проекте, то эта свобода может перерасти в панику.

Давайте взглянем на данный код.

const pikachu = (a, b) => {
  return a + b;
}

Можете ли вы угадать, что вернет этот код?

Я не могу, т.к. функция pikachu может принимать в себя значения любого типа, к примеру, строка, число и т.д.

// Передается число.
const pikachu = (a, b) => {
  return a + b;
}
const result = pikachu(2021, 9);
console.log(result); // 2030
// Передается строка.
const pikachu = (a, b) => {
  return a + b;
}
const result = pikachu("2021", "9");
console.log(result); // 20219

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

С другой стороны, пожалуйста, посмотрите на данный код.

const pikachu = (a: number, b: number): number => {
  return a + b;
}

Данный код на typescript. TypeScript – это язык с статической типизацией. Когда мы смотрим на это, мы сразу можем понять, что значение, которое возвращает функция pikachu будет числом.

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

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

Основы TypeScript

TypeScript имеет несколько примитивный типов данных, таких как string, number, boolean, null, undefined.

Это код с простыми типами данных.

const caterpie01: number = 2021;    // OK
const caterpie02: number = false;   // Не ок

const Metapod01: string = "sleepy"; // OK
const Metapod02: string = true;     // Не ок

const Wartortle01: boolean = true;  // OK
const Wartortle02: boolean = 1111;  // Не ок

При запуске кода мы сразу встречаем несколько ошибок.

typescript.ts:10:7 - error TS2322: Type 'boolean' is not assignable to type 'number'.

10 const caterpie02: number = false;   // Не ок
         ~~~~~~~~~~

typescript.ts:13:7 - error TS2322: Type 'boolean' is not assignable to type 'string'.

13 const Metapod02: string = true;     // Не ок
         ~~~~~~~~~

typescript.ts:16:7 - error TS2322: Type 'number' is not assignable to type 'boolean'.

16 const Wartortle02: boolean = 1111;  // Не ок
         ~~~~~~~~~~~

Дальше, давайте посмотрим на null и undefined.

const Butterfree: null = null;
const ButterfreeNull: string = Butterfree;
console.log(ButterfreeNull) // null

const Kakuna: undefined = undefined;
const KakunaNull: string = Kakuna;
console.log(KakunaNull) //undefined

Этот код работает. Мы можем устанавливать значения null и undefined строкам. В данном случае, я не использовал strict mode. При использовании же, код работает примерно так.

typescript.ts:21:7 - error TS2322: Type 'null' is not assignable to type 'string'.

21 const ButterfreeNull: string = Butterfree;
         ~~~~~~~~~~~~~~

typescript.ts:25:7 - error TS2322: Type 'undefined' is not assignable to type 'string'.

25 const KakunaNull: string = Kakuna;

И это хорошо! Мы сразу можем отлавливать ошибки.

Вы можете установить strict mode в tsconfig.json или использовать аргумент командой строки tsc --strict. Если вы не уверен, в том, как настраивать typescript, вы модете посмотреть примеры на офф. сайте.

Что такое тип данных “any”?

В TypeScript можно использовать тип данных any. Это позволяет работать с любым типом данных без ошибок. Прямо как в обычном javascript.

Давайте взглянем на пример кода.

let pidgey: any = 1991;
console.log(typeof pidgey) // number

pidgey = "bird";
console.log(typeof pidgey) // string

pidgey = false;
console.log(typeof pidgey) // boolean

pidgey = null;
console.log(typeof pidgey) // object

pidgey = undefined;
console.log(typeof pidgey) // undefined

Переменной pidgey можно присвоить любой тип данных!

Это магический тип данных. ?

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

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

const caterpie01: number = 2021;     // number
const caterpie001 = 2021;            // number  - выбор typescript 


const Metapod01: string = "sleepy";  // string
const Metapod001 = "sleepy";         // string  - выбор typescript 

const Wartortle01: boolean = true;   // boolean
const Wartortle001 = true;           // boolean - выбор typescript 

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

let caterpie001 = 2021;            // number
caterpie001 = "text";              // type error

С другой стороны, если мы не укажем тип данных для аргументов функции, typescript выберет тип any. Посмотрим на код.

const pikachu = (a, b) => {
  return a + b;
}
pikachu(2021, 9);

Я получил вот такие ошибки. (В данный момент у меня включен strict mode. Если же его выключить, то код прекрасно отработает)

typescript.ts:57:18 - error TS7006: Parameter 'a' implicitly has an 'any' type.

57 const pikachu = (a, b): number => {
                    ~

typescript.ts:57:21 - error TS7006: Parameter 'b' implicitly has an 'any' type.

57 const pikachu = (a, b): number => {

Всё из-за того, что typescript не может узнать какое значение будет получено.

Для этого тип данных any и был добавлен в typescript. Когда мы используем функции в typescript, мы должны указывать типы данных для аргументов, как на примере.

const pikachu = (a: number, b: number): number => {
  return a + b;
}

Или

// можно также не указывать какой тип данных будет возвращаться
const pikachu = (a: number, b: number) => {
  return a + b;
}

Если вы создаете функцию в typescript, вы обязаны указывать тип данных. Я также рекомендую не использовать тип данных any, за исключением специфичных ситуаций. Таких, как, к примеру, при миграции с JavaScript на TypeScript.

Тип данных для объектов

TypeScript позволяет указывать тип данных для объектов через interface.
Посмотрим на пример.

// Определяем типы данных для объекта
interface PokemonObj {
  name: string,
  age: number,
  skill: string
}
// Назначаем типы
const pokemon: PokemonObj = {
  name: "pikachu",
  age: 6,
  skill: "Electric Shock!"
}

Мы можем использовать interface для создания типа данных для объектов. А затем назначать interface в объекте.
Если мы изменим тип данных внутри объекта, то получим ошибку.

// Определяем типы данных для объекта
interface PokemonObj {
  name: string,
  age: number,
  skill: string
}
// Назначаем типы
const pokemon: PokemonObj = {
  name: "pikachu",
  age: "change age", // изменили
  skill: "Electric Shock!"
}

Ниже текст ошибки.

typescript.ts:75:3 - error TS2322: Type 'string' is not assignable to type 'number'.

75   age: "change age",
     ~~~

  typescript.ts:69:3
    69   age: number,
         ~~~
    The expected type comes from property 'age' which is declared here on type 'PokemonObj'

Мы получаем ошибку типов. Удобно использовать interface как тип данных у объектов. Но, конечно же, мы можем описывать тип данных объекта сразу в коде, прямо как на примере.

const pokemon: {name: string, age: number, skill: string} = {
  name: "pikachu",
  age: 6,
  skill: "Electric Shock!"
}

Тип данных для массивов

Массив с типами данных выглядит вот так.

const pokemon: string[] = ["pikachu", "Raichu", "Charizard"];

Если мы изменим тип данных, то получим ошибку.

const pokemon: string[] = ["pikachu", "Raichu", false];

Текст ошибки.

typescript.ts:80:49 - error TS2322: Type 'boolean' is not assignable to type 'string'.

80 const pokemon: string[] = ["pikachu", "Raichu", false];

Это полезно, так как нам не приходится заботиться о типе данных для каждого элемента массива. Кстати, можно записать тип данных и по-другому. Это такой же код, как и на примере выше.

const pokemon: Array<string> = ["pikachu", "Raichu", "Charizard"];

Следующим типом данных будут generics(дженерики). Это обширный тип данных. После создания дженерик типа, мы можем определить его. Пример кода ниже.

// Определяем тип данных для массива как дженерик
type Pokemon<T> = T[];
// После, мы можем указывать любой тип данных
const pokemon: Pokemon<string> = ["pikachu", "Raichu", "Charizard"];

// Тоже самое, что и код выше
const pokemon: string[] = ["pikachu", "Raichu", "Charizard"];

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

// Определяем тип данных для массива как дженерик
type Pokemon<T> = T[];
// После создания дженерика, мы можем выбрать любой тип данных
const pokemon01: Pokemon<string> = ["pikachu", "Raichu", "Charizard"];
const pokemon02: Pokemon<number> = [6, 14, 16];
const pokemon03: Pokemon<boolean> = [true, true, false];

Что такое union?

При использовании union, вы можете указывать сразу несколько типов данных. Пожалуйста, посмотрите на пример кода.

let pokemon: (string | number) = "pikachu";  // OK
pokemon = 6; 

Этот код отработает правильно, т.к. переменная pokemon может быть как строкой, так и числом. Но код ниже не верен

let pokemon: (string | number) = "pikachu";
pokemon = 6;
pokemon = false;      // Не ок

Так как переменная pokemon не может принимать в себе тип данных Boolean, то компилятор выдаст ошибку. Если же вы хотите создать массив, в котором будет использоваться несколько разных типов данных, то вы можете также использовать union.
Пример кода.

// массив с использованием union
let pokemon: (string | number)[] = ["pikachu", "Raichu", 6, 14];

Этот код верный. Но, если мы добавим другой тип данных, мы получим ошибку.

typescript.ts:105:65 - error TS2322: Type 'boolean' is not assignable to type 'string | number'.

105 let pokemon: (string | number)[] = ["pikachu", "Raichu", 6, 14, false];

Если вы будете добавлять в массив значения с разными типами, то union ваш выбор.

Что такое tupple?

Tupple – это точный тип данных.
Для начала, давайте взглянем на пример.

let pokemon: [string, number] = ["pikachu", 6];

Этот код сработает отлично. Данный тип данных, tupple, позволяет нам указывать только 2 элемента, строку и число, в определенном порядке.
Сейчас я вам покажу что будет, если указывать данные с ошибками.

typescript.ts:109:36 - error TS2322: Type 'number' is not assignable to type 'string'.

109 let pokemon02: [string, number] = [6, "pikachu"];      // Не ок
                                       ~

typescript.ts:109:39 - error TS2322: Type 'string' is not assignable to type 'number'.

109 let pokemon02: [string, number] = [6, "pikachu"];      // Не ок
                                          ~~~~~~~~~

typescript.ts:110:47 - error TS2322: Type 'string' is not assignable to type 'number'.

110 let pokemon03: [string, number] = ["pikachu", "text"]; // Не ок
                                                  ~~~~~~

typescript.ts:111:5 - error TS2322: Type '[string, number, number]' is not assignable to type '[string, number]'.
  Source has 3 element(s) but target allows only 2.

111 let pokemon04: [string, number] = ["pikachu", 6, 14];  // Не ок

Тип данных Tupple это сама точность. И, в данном случае, это позволяет нам легко понять предназначение массива, и что он вмещает только 2 элемента. Первый, это строка, а второй, это число.

Выводы

В данном посте я описал базовые типы данных TypeScript’а.

Если вы хотите изучать typescript, то вы можете посмотреть на npm пакеты, созданный на typescript, а также будете писать более читаемый и поддерживаемый код.
Если вы работаете в компании, то знаете, как много кода может быть. Так что, вам приходится читать, а также понимать его в больших количествах. TypeScript помогает понимать код!

Спасибо что потратили своё время на прочтение данного поста.

Tags:
Hubs:
Total votes 17: ↑7 and ↓10-2
Comments29

Articles