Друкарня від WE.UA

TypeScript - JavaScript тільки з типами, якось так коротко можна це описати щоб всі зрозуміли.

TypeScript - може як прискорювати роботу так і уповільнювати її в залежності від правильності використання, приклади:

  1. При типізації API - це явно прискорюватиме роботу як для людей які уже працюють над проєктом, так і для людей які будуть над ним працювати. [USEFULL]

  2. Типізація все-можливих подій по типу клік на елемент який знаходиться всередині іншого елементу лише для того щоб взяти властивість висоти елементу - крінж. [USELESS]

Нижній Текст
У цій статті будуть певні приклади коду та техніки використання можливостей TypeScript які спростять та збільшать швидкість написання коду.

Примітиви

Загальні типи

Документація говорить що є всього 3 примітивних типи:

type Primitive = string | boolean | number;

Можна також додати сюди symbol - 99% випадків вам це не знадобиться.

Також можна розширити і додати undefined, null, але це не правильно, так як у undefined, null - немає ніяких методів. Краще буде зробити окремий тип Nullable і використовувати оператор “?” - для випадків з undefined;

type Nullable<T> = T | null;

type Primitive = string | boolean | number | symbol | null | undefined;

type DTO = { field: Primitive };


type Primitive1 = string | boolean | number | symbol;

type DTO1 = { field?: Nullable<Primitive> };

При роботі із першим типом ви завжди будете отримувати помилку - “'.field' is possibly 'null' or 'undefined'.”

При роботі з другим варіантом ви будете отримувати ці повідомлення тільки якщо обернете у Nullable або поле буду опціональним, це дасть вам більшу гнучкість при типізації.

Оверхед

При роботі з примітивами супер-типізація може згубно впливати на швидкість написання коду.

Потрібно враховувати межу коли це - “Упоротий" або “Валідний" код.

приклад:

const [count, setCount] = useState<number>(0); // OK
const [count, setCount] = useState<0 | 1 | 2>(0); // not OK

У другому випадку може бути валідно тільки у якщо не потрібно щоб count був щось окрім “0, 1, 2", але краще це опрацювати на рівні своєї сет-функції

const handleUpdateCounter = (newCount: number) => {
  if(newCount > 2) return;
  setCount(newCount);
}

Місце де можна використати щось типу такого - це статуси або конкретні числові або текстові значення.

type USER_STATUS_TYPE = "REGISTERED" | "VERIFIED" | "BLOCKED";

але також потрібно враховувати те що вам потрібно буде використовувати значення цього типу для перетворення або порівняння, тоді краще використати enum.

enum USER_STATUS_ENUM {
  REGISTERED = "REGISTERED",
  VERIFIED = "VERIFIED",
  BLOCKED = "BLOCKED"
}

const userStatus: USER_STATUS_ENUM = ...;

для складних операцій із подібними типами, або для використання такого роду типів за межами рендеру - краще обрати об’єкти.

const USER_STATUS_ENUM = {
  REGISTERED: "REGISTERED",
  VERIFIED: "VERIFIED",
  BLOCKED: "BLOCKED"
}

type UserStatus = keyof typeof USER_STATUS_ENUM;

const isValidType = (userStatus: UserStatus) => Object.values(USER_STATUS_ENUM).includes(userStatus);
Звісно при грамотній типізації цей кейс вам не доведеться використовувати, але якщо текстові данні потрапляють із форми яку ввів користувач, або ви дуже не довіряєте API то додати подібну перевірку - зайвим не буде.

Шаблонні рядки

Це один із видів заплутування розробників, який у більшості випадків використовується людьми які знають що їм потрібно.

type StringUrlPattern = `http://${string}.${string}`;
const url: StringUrlPattern = 'http://google.com' // - correct;
const url1: StringUrlPattern = 'http://google' // - error;

Крута штука, яку варто знати, але також це може викликати багато проблем:

  1. Уповільнює рефакторинг

  2. Без коментарів новим розробникам ваші рішення можуть бути не очевидними.

  3. При зав’язуванні всієї логіки певного модуля на таких типах, його розширення - це дуже складна задача, бо новий функціонал не завжди ідеально натягується на старий.

type StringUrlPattern = `http://${string}.${string}`;
const url: StringUrlPattern = 'http://google.com' // - correct;
const url1: StringUrlPattern = 'http://google' // - error;

const url2: StringUrlPattern = 'http://google.com.com.com' // - correct;
const url3: StringUrlPattern = 'http://..' // - correct;

Ось які проблеми можуть чекати на вас якщо довіряти лише типам, це не очевидні речі, які можуть викликати додаткову купу функцій-валідацій, які у свою чергу перекриють всю ідею шаблонних рядків.

Враховуйте ці пункти при використанні шаблонних рядків.

Допоміжні типи

type Str1 = Uppercase<"text">; // TEXT

type Str2 = Lowercase<"TEXT">; // text

type Str3 = Capitalize<"text">; // Text

type Str4 = Uncapitalize<"Text"> // text;

type Str5<S extends string = 'TEST'> = `${Lowercase<S>}-%{S}; // test-TEST

По назвах цих типів уже можна зрозуміти як вони працюють, якщо їх використовувати із шаблонними рядками - це створить щось магічне і неочевидне, тому варто використовувати у випадках коли ви дійсно впевнені у користі цих типів.

never | unknown | any

any

any - будь-яке значення. Але правильніше говорити що any - просто ігнорує типи, а не є чим завгодно. Можливі різні комбінації:

type Type = any;
type Type1 = any[];
type Type1 = Record<string, any>;

const entity = {} as any;

never

never - ніколи. Це означає що цього значення ніколи не може бути, найчастіше використовується у функціях щоб сказати що ця функція ніколи нічого не повертає, якщо ви напишете return у такій функції - отримаєте помилку.

Лайфхак:

const USER_STATUS_ENUM = {
  REGISTERED: "REGISTERED",
  VERIFIED: "VERIFIED",
  BLOCKED: "BLOCKED",
}

type Status = keyof typeof USER_STATUS_ENUM;

function assertNever(value: never): never {
  throw new Error(`Unexpected value: ${value}`);
}


function getStatusLabel(status: Status) {
  switch (status) {
    case "BLOCKED":
      return 'Block';
    case "VERIFIED":
      return 'Verify';
    case "REGISTERED":
      return 'Register';
    default:
      assertNever(status);  // If you forgot update 'cases', TypeScript will show compile-time error here.
  }
}

Якщо додати ще одне поле у об’єкт USER_STATUS_ENUM - ви отримаєте помилку “Argument of type 'string' is not assignable to parameter of type 'never'.” - за допомогою таких маленьких лайфхаків можна зекономити собі багато часу при розширенні коду.

unknown

unknown - менше зло ніж any але теж маленьке зло. Цей тип використовується коли ви хочете позначити щось, але не знаєте що там, у той час як any - відключає типізацію, unknown - говорить що тут буде якась значення, але поки не ясно яке, при роботі із unknown його потрібно переприсвоювати.

type Response = { name: string };
const a = apiResponse as unknown as Response;

так краще не робити, але це приклад того як можна використати unknown.

const data: unknown = getValueFromExternalLibraryWithoutTypes();

у таких випадках unknown - це найкращий тип який можна використати.

const data: unknown = getValueFromExternalLibraryWithoutTypes();
let localData: string;

localData = data; // Error;

якби тут ми використали any - була б біда.

Підсумки

Лише з примітивами можна значно покращити “DX” команди при роботі з TypeScript.

Деякі із цих речей очевидні і можуть здаватись занадто простими, але про них потрібно пам’ятати щоб використовувати всі можливості TypeScript.

На цьому завершу. Розкрити всі теми і лайфхаки TypeScript у одному довгочиті дуже складно, і це буде не інформативно, тому у наступних статтях буде більше цікавих можливостей TypeScript.

Статті про вітчизняний бізнес та цікавих людей:

  • Вітаємо з Різдвом Христовим!

    Друкарня та платформа WE.UA вітають всіх наших читачів та авторів зі світлим святом Різдва! Зичимо всім українцям довгожданого миру, міцного здоровʼя, злагоди, родинного затишку та втілення всього доброго і прекрасного, чого вам побажали колядники!

    Теми цього довгочиту:

    Різдво
  • Каблучки – прикраси, які варто купувати

    Ювелірні вироби – це не тільки спосіб витратити гроші, але і зробити вигідні інвестиції. Бо вартість ювелірних виробів з кожним роком тільки зростає. Тому купуючи стильні прикраси, ви вигідно вкладаєте кошти.

    Теми цього довгочиту:

    Як Вибрати Каблучку
  • П'ять помилок у виборі домашнього текстилю, які псують комфорт сну

    Навіть ідеальний матрац не компенсує дискомфорт, якщо текстиль підібрано неправильно. Постільна білизна безпосередньо впливає на терморегуляцію, стан шкіри та глибину сну. Більшість проблем виникає не через низьку якість виробів, а через вибір матеріалів та подальшу експлуатацію

    Теми цього довгочиту:

    Домашній Текстиль
  • Як знайти житло в Києві

    Переїжджаєте до Києва і шукаєте житло? Дізнайтеся, як орендувати чи купити квартиру, перевірити власника та знайти варіанти, про які зазвичай не говорять.

    Теми цього довгочиту:

    Агентство Нерухомості
  • Як заохотити дитину до читання?

    Як залучити до читання сучасну молодь - поради та факти. Користь читання для дітей - основні переваги. Розвиток дітей - це наше майбутнє.

    Теми цього довгочиту:

    Читання
Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Valentyn Tupota
Valentyn Tupota@valentyn_tupota

Software Engineer

1.8KПрочитань
3Автори
37Читачі
На Друкарні з 11 жовтня

Більше від автора

  • Articles

    Зміст

    Теми цього довгочиту:

    Content
  • Neural Network [guide] 1

    Все починається із першого нейрону. Алгоритм лінійної регресії для одного нейрону, та принципи його використання.

    Теми цього довгочиту:

    It
  • Frontend [TypeScript] 2

    TypeScript - Як писати код швидше та надійніше. Про неочевидні речі.

    Теми цього довгочиту:

    It

Це також може зацікавити:

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Це також може зацікавити: