5 marca 20234 min. czytania

TypeScript - podstawowe typy

Wraz z rosnącym wykorzystaniem TypeScripta, myślę, że nadszedł czas, aby zacząć się go uczyć. Czym jest? Po co go używać? Postaramy się odpowiedzieć na te pytania i nauczyć się kilkunastu podstawowych typów.

Ostatnia aktualizacja 5 marca 2023
Kłódka w kolorze morskim zamykająca niebieską bramkę
Zdjęcie autorstwa Maxim Zhgulev

Niedawno zacząłem uczyć się TypeScripta (w zasadzie kodowałem wcześniej w Angularze, więc TypeScript nie jest dla mnie zupełnie nowy, ale od tamtej pory nie używałem go często). Na początku miałem wątpliwości, nie będę kłamał. Kod w tym języku wydawał mi się opasły i nieelegancki. Ale bądźmy szczerzy - jedynym minusem TypeScripta jest to, że musisz poświęcić czas na naukę. Jestem tylko człowiekiem, więc zmiana może być przerażająca. Ale jedyną stałą życiu jest zmiana. Zmiany mogą być dobre. A wraz z rosnącym wykorzystaniem TypeScripta, to jest dobry moment żeby zacząć się go uczyć. Ucz się ze mną!

Czym jest TypeScript?

U podstaw, TypeScript jest nadzbiorem JavaScriptu. Co to znaczy? Już wyjaśniam zagadnienie. Pewnie pamiętasz zbiory ze szkoły - wiesz, te przecinające się kółka. Jest to diagram Venna - graficzna reprezentacja, która pokazuje logiczne relacje pomiędzy tymi zbiorami. Podobna relacja zachodzi pomiędzy językiem JavaScript i TypeScript - TypeScript to nadzbiór JavaScriptu lub JavaScript to podzbiór TypeScripta. Każda linia kodu JS jest poprawnym kodem TS, ale nie odwrotnie.

JavaScript i TypeScript diagram venna

To znaczy, że TypeScript rozbudowuje JavaScript. Dodaje nowe funkcjonalności i zalety względem “waniliowego” języka. W zasadzie, TypeScript to zarówno język jak i narzędzie. Jest to potężny kompilator, który uruchamiasz, żeby skompilować kod TS do JS. Dlaczego? Bo przeglądarki rozpoznają tylko kod JS.

Dlaczego używać TypeScripta?

W programowaniu chodzi o myślenie, a nie o pisanie.

“No dobra, po co pisać kod, którego przeglądarki nie rozpoznają?”. Istnieje kilka zalet.

  • Przede wszystkim, TypeScript zmusza cię, abyś myślał więcej o swoim kodzie i celach. Wszystkie twoje intencje są spisane - nie ma miejsca na domysły.
  • TypeScript dodaje nowe funkcjonalności - niedostępne w bazowym języku - jak np. interfejsy czy generyki.
  • TypeScript oferuje meta-programistyczne funkcjonalności jak dekoratory.
  • Dzięki krokowi kompilacji, możesz używać współczesnej składni języka JavaScript i nie przejmować się wsparciem dla przeglądarek. Jest to podobna zaleta jak w przypadku używania kompilatora Babel.
  • Wiele opcji konfiguracji - możesz skonfigurować kompilator według swoich potrzeb.
  • Jak nazwa wskazuje, oferuje on typy. Na nich skupimy się w następnych sekcjach.
  • Lepsze autouzupełnianie w edytorach tekstu i IDE.

Typy JavaScript, a typy TypeScript

JavaScript jest dynamicznie typowanym językiem. Typy są ustalane w trakcie pracy skryptu. Ma to swoje zalety, ale może powodować wiele błędów.

TypeScript jest typowany statycznie. Definiujemy typy podczas rozwoju oprogramowania. Nie zmieniają się po uruchomieniu skryptu.

Typy TypeScript

Zacznijmy od tego, że TypeScript dostarcza dodatkowe typy do języka JavaScript. Istnieją typy które są dostępne zarówno w JavaScripcie jak i w TypeScripcie. Ale istnieją też typy dostarczone przez nasz nadzbiór.

Podstawowe typy dostępne w JS i TS to:

  • number
  • string
  • boolean
  • object
  • array

Dodatkowe typy oferowane przez TypeScript to m.in.:

  • Tuple
  • Enum
  • Any
  • Union
  • Literal
  • Custom

Przypisywanie typów

JavaScript nie rozumie składni przypisywania TypeScripta. Typy są używane przez kompilator TS. TypeScript ma wbudowaną funkcjonalność nazwaną wnioskowaniem typu. TS robi co może, aby zrozumieć typ konkretnej zmiennej lub stałej. Dlatego nie musisz ich ręcznie deklarować za każdym razem. Aby przypisać typ do zmiennej możesz wykorzystać dwukropek.

TYPESCRIPT
1let name: string // Zmienna name ma typ string.

Wszystkie podstawowe typy w TypeScripcie są zapisane z małej litery.

Number

Podobnie do bazowego języka, TypeScript nie definiuje różnych typów liczb. Liczby w JavaScript są zapisywane zawsze jako liczby zmiennoprzecinkowe podwójnej precyzji, zgodne ze standardem IEEE 754 lub jako big integers.

TYPESCRIPT
1const PI = 3.14 // TypeScript wnioskuje, że ta liczba zawsze powinna równać się 3.14.
2let age = 25 // TypeScript wnioskuje, że to ma być liczba.
3// W przypadku maksymalnego wieku dziewczyny DiCaprio to równiez jest stała - wiem.
4let age: number = 25 // Ten kod działa ale jest redundantny - zła praktyka.
5let age: number // Tu ma to sens, ponieważ nie ma inicjalizacji zmiennej.

String

Aby zdefiniować string, użyj cudzysłowów podwójnych lub pojedynczych. Template strings, wykorzystując odwrotny apostrof, też są opcją.

TYPESCRIPT
1const maxim = "Medals don't help me sleep at night." // TypeScript wnioskuje, że ten string jest stały.
2let name = "Sam" // TypeScript wnioskuje, że powinien być to typ string.
3let name: string // Tej zmiennej będzie przypisany string.

Boolean

Najbardziej podstawowy typ danych - reprezentuje wartość true lub false. W przeciwieństwie to JavaScriptu, TypeScript nie posiada wartości “truthy” i “falsy”.

TYPESCRIPT
1let isDone: boolean

Object

Typ obiektu definiujesz podobnie do standardowych obiektów JS. Jednakże zamiast par klucz-wartość, zapisujesz pary klucz-typ. Przyjrzyj się składni - odrobinę się różni.

TYPESCRIPT
1const person = {
2 name: "Sam",
3 age: 66,
4}
5
6// TypeScript wnioskuje.
7const person: {
8 name: string
9 age: number
10}
11
12// Tak możesz definiować generyczne obiekty.
13const person: object = {
14 name: "Sam",
15 age: 66,
16}
17
18// Możesz także zdefiniować bardziej konkretną strukturę obiektu.
19const person: { name: string } = {
20 name: "Sam",
21 age: 66, // Tej właściwości nie ma w typie, więc powoduje błędy.
22}

Array

W języku JavaScript, możesz mieszać różne typy danych - jedna tablica może składać się z liczb i łańcuchów znaków. Każda tablica JS jest poprawną tablicą TS. Tablice TS mogą być elastyczne, ale również restrykcyjne.

TYPESCRIPT
1const person = {
2 hobbies: ["Krav maga", "sneaking"],
3}
4
5// TypeScript wnioskuje.
6const person: {
7 hobbies: string[]
8}
9
10// Możesz zdefiniować restrykcyjna tablicę zawierającą tylko łańcuchy znaków.
11let hobbies: string[]
12
13// Możesz także zdefiniować bardziej elastyczną tablicę.
14let hobbies: any[]

Tuple

Typ tuple nie jest dostępny w języku JavaScript - jest dodany przez TypeScript. Tuple to tablica o stałej długości i typie. Może być przydatna, gdy wcześniej znasz dokładną strukturę tablicy.

TYPESCRIPT
1const person = {
2 role: [3, "agent"],
3}
4
5// TypeScript wnioskuje.
6const person: {
7 role: (string | number)[]
8}
9
10// Możesz wyraźnie zdefiniować strukturę typu tuple.
11const person: {
12 role: [number, string]
13} = {
14 role: [3, "agent"],
15}

Enum

Enum to niestandardowy typ w języku TypeScript. Daje ci wyliczoną listę. Typ enum mapuje czytelne dla człowieka etykiety do liczb, zaczynając od 0. Nie jest dostępny w JavaScripcie i zostaje skompilowany do IIFE.

TYPESCRIPT
1// Etykiety są często zapisane wielkimi literami.
2enum Role {
3 AGENT,
4 INTEL,
5}
6
7const person = {
8 role: Role.AGENT,
9}
10
11// Możesz zmienić domyślne zachowanie typu enum.
12enum Role {
13 AGENT = "AGENT",
14 INTEL,
15}

Union

Czasami chcesz akceptować więcej niż jeden rodzaj wartości. W takiej sytuacji przydaje się typ union. Możesz zdefiniować unie wykorzystując znak poziomej kreski pomiędzy różnymi typami.

TYPESCRIPT
1// Oba parametry tej funkcji mogą być zrówno liczbą jak i ciągiem znaków.
2function combine(i1: number | string, i2: number | string) {
3 const result = i1 + i2
4 return result
5}

Literal

Wspomniałem o tym typie w poprzednich fragmentach kodu, ale czas zdefiniować go oddzielnie. Typ literal nie określa tylko typu zmiennej, ale także mówi: “ta zmienna powinna otrzymać tę konkretną wartość”.

TYPESCRIPT
1const PI = 3.14 // TypeScript oczekuje tej konkretnej liczby, nie dowolnej liczby.
2
3function combine(
4 i1: number | string,
5 i2: number | string
6 // Union połączone z typem literal - tylko dwa możliwe łańcuchy znaków.
7 conversion: "as-text" | "as-number"
8) {
9 const result = i1 + i2
10 return result
11}

Custom

Poza wbudowanymi typami, TypeScript pozwala ci także definiować niestandardowe typy (znane także jako aliasy typów). Istnieje specjalne słowo kluczowe - type - do tego celu. Możesz wrzucić cokolwiek do niestandardowego typu: sting, obiekt czy unie. Po zdefiniowaniu niestandardowego typu, możesz użyć tego aliasu w wielu miejscach w kodzie. W ten sposób unikasz duplikacji kodu.

TYPESCRIPT
1// Konwencja mówi, żeby definować niestadardowe typy z wielkiej litery.
2type State = "idle" | "loading" | "success"
3
4type Person = {
5 name: string
6 age: number
7}

Możesz wykorzystać dowolną nazwę dla niestandardowego typu, ale nie możesz wykorzystać zarezerwowanych słów kluczowych języka JavaScript (lub TypeScript) jak Date czy Math.

Typy parametrów funkcji

W poprzednich fragmentach kodu, ustawiałem typy parametrom funkcji. Możesz je dodawać po każdym parametrze wykorzystując standardową składnię.

TYPESCRIPT
1// Funkcja ma dwa parametry, gdzie każdy z nich to liczba.
2function add(n1: number, n2: number) {
3 return n1 + n2
4}

Typy zwracane przez funkcję

Podobnie możesz ustawiać typy wartościom zwracanym przez funkcje. void jest często używany z funkcjami, które nie zwracają żadnej wartości. Jest jak przeciwieństwo typu any - brak jakiejkolwiek wartości.

TYPESCRIPT
1function add(n1: number, n2: number) {
2 return n1 + n2
3}
4
5// TypeScript wnioskuje.
6function add(n1: number, n2: number): number {
7 return n1 + n2
8}
9
10// Możesz wyraźnie zaznaczyć typ zwracanej wartości
11// ale w większości wypadków TypeScript może go wywnioskować.
12function add(n1: number, n2: number): string {
13 return n1.toString() + n2.toString()
14}
15
16// Możesz użyć typu void
17// jeżeli funkcja nie zwaraca wartości.
18function printResult(num): void {
19 console.log("Result: " + num)
20}
21
22// Undefined to poprawny typ w TypeScript,
23// ale nie gdy funkcja niczego nie zwraca.
24function printResult(num: number): undefined {
25 console.log("Result: " + num)
26}

Wyrażenie typu funkcji

Istnieje także typ Function w języku TypeScript. Opisuje on właściwości takie jak bind lub apply - dostępne we wszystkich funkcjach w JavaScripcie. Jednakże, deklarowanie niespecyficznej funkcji nie jest zbyt przydatne. Lepszym sposobem na ich opisywanie jest wyrażenie typu funkcji. Jeżeli przypomina ci funkcje strzałkowe - masz rację - składnia jest podobna.

TYPESCRIPT
1// Deklarowanie niespecyficznej funkcji.
2let combineValues: Function
3
4// Ta funkcja przyjmuje dwa parametry, gdzie każdy z nich to liczba.
5// Funcja ogólnie zwaraca liczbę.
6let combineValues: (a: number, b: number) => number

Unknown

Istnieje inny nieznany dla nas typ (hehe). Jest podobny do typu any, ale jest bezpieczniejszy. Nie możesz zrobić czegokolwiek z typem unknown.

TYPESCRIPT
1let input: unknown
2let name: string
3
4input = 5
5name = "Sam"
6// To nie zadziała, ponieważ nie ma gwarancji,
7// że typ unknown będzie stringiem.
8name = input
TYPESCRIPT
1let input: any
2let name: string
3
4input = 5
5input = "Sam"
6// Z drugiej strony, to zadziała, ponieważ
7// typ any jest najbardziej elastyczny.
8name = input

Never

Niektóre funkcje w JavaScripcie nigdy nie zwracają wartości. “Chwila, moment, czym się to różni od typu void?”. Musimy zagłębić się w język JavaScript, aby odpowiedzieć na to pytanie.

Funkcja, w której nie ma wyrażenia return, nadal zwraca undefined w języku JavaScript. Mogłeś zaobserwować to zachowanie przy funkcjach, które logują coś w konsoli. Pomimo że ignorujemy tę wartość, ona tam nadal jest. Jest to dobre miejsce na wykorzystanie typu void.

Funkcja która ma przypisany typ never, nigdy nie zwraca wartości. Nie zwraca nawet domyślnego undefined. Taka sytuacja zachodzi, gdy funkcja wyrzuca error.

TYPESCRIPT
1// Ta funkcja nigdy nie zwraca wartości. Ona psuje skrypt.
2function generateError(message: string, code: number): never {
3 throw { message: message, errorCode: code }
4}

No dobra, nigdy (hehe) nie powiedziałem, że pokryje wszystkie typy w jednym wpisie. TypeScript oferuje nawet więcej podstawowych i zaawansowanych typów, które mogą ci pomóc w produkowaniu przewidywalnego kodu, który jest łatwy w utrzymaniu. W przyszłości przybliżę także bardziej zaawansowane koncepty, takie jak generyki, interfejsy czy dekoratory. W międzyczasie możesz sprawdzić poniższe linki:

Moje zdjęcie profilowe, gdzie jestem w białej koszulce na szarym, gradientowym tle. Połowa mojej twarzy jest w cieniu. Druga połowa jest prawidłowo oświetlona.

Inżynier oprogramowania o erudycyjnych aspiracjach.

Przeczytaj więcej. Pozostań ciekawy

Połowa winyla na białym tle
1 września 2022 • 3 min. czytania

Dostępne animacje w React

Czyli jak nie kręcić swoimi użytkownikami (jak winylem). Niektóre animacje mogą powodować problemy u użytkoników. Zadbamy o nich i sprawimy, że nieistotne animacje będą opcjonalne.

Czytaj wpis
Pięć metalowych kół zębatych na czarnym tle
23 września 2022 • 5 min. czytania

Gatsby z Netlify CMS

W tym wpisie przyjrzymy się bliżej Netlify CMS. Jest to przykład CMSa nowego typu, który jest oparty o Git. Zintegrujemy go z przykładowym projektem Gatsby.

Czytaj wpis
Zdjęcie zmiennych CSS w edytorze Visual Studio Code
14 września 2022 • 3 min. czytania

Konwertowanie tokenów projektowych na zmienne CSS z Node.js

Konwertowanie tokenów projektowych jest procesem podatnym na błędy - przekonałem się o tym na własnej skórze. Dlatego stworzyłem prosty skrypt dla środowiska Node.js, który pomoże mi z tym zadaniem.

Czytaj wpis

Newsletter, który rozpala ciekawość💡

Subskrybuj mój newsletter, aby otrzymywać comiesięczną dawkę:

  • Nowości, przykładów, inspiracji ze świata front-end, web development’u i designu
  • Teorii naukowych i sceptycyzmu
  • Moich ulubionych źródeł, idei, narzędzi i innych interesujących linków
Nie jestem nigeryjskim księciem, aby oferować ci okazje. Nie wysyłam spamu. Anuluj kiedy chcesz.