Naučte se TypeScript za 30 minut

Dnes se podíváme na TypeScript, jazyk kompilující do JavaScriptu určený pro vývojáře, kteří vytvářejí velké a složité aplikace. Přebírá mnoho programovacích konceptů z jazyků jako C# a Java, které dodávají jinak velmi uvolněnému JavaScriptu s volným typem více disciplíny a řádu.

Tento tutoriál je zaměřen na lidi, kteří jsou poměrně zběhlí v JavaScriptu, ale jsou stále začátečníky, pokud jde o TypeScript. Pokryli jsme většinu základů a klíčových funkcí a zároveň jsme zahrnuli spoustu příkladů s komentovaným kódem, které vám pomohou vidět jazyk v akci. Začněme!

Výhody používání TypeScript

JavaScript je docela dobrý tak, jak je, a možná se ptáte Opravdu se potřebuji naučit TypeScript? Technicky to nepotřebujete naučit se TypeScript být dobrým vývojářem, většina lidí se bez něj obejde. Nicméně práce s TypeScriptem má rozhodně své výhody:

  • Kvůli statickému psaní je kód napsaný v TypeScript předvídatelnější a obecně se snáze ladí.
  • Usnadňuje organizaci kódové základny pro velmi velké a komplikované aplikace díky modulům, jmenným prostorům a silné podpoře OOP.
  • TypeScript má kompilační krok do JavaScriptu, který zachytí všechny druhy chyb dříve, než dosáhnou běhu a něco pokazí.
  • Připravovaný framework Angular 2 je napsán v TypeScriptu a doporučuje se, aby vývojáři tento jazyk používali také ve svých projektech.

Poslední bod je ve skutečnosti pro mnoho lidí nejdůležitější a je hlavním důvodem, proč je dostat do TypeScriptu. Angular 2 je v současnosti jedním z nejžhavějších frameworků a ačkoli s ním vývojáři mohou používat běžný JavaScript, většina tutoriálů a příkladů je napsána v TS. Jak Angular 2 rozšiřuje svou komunitu, je přirozené, že TypeScript bude používat stále více lidí.

Instalace TypeScript

Nejjednodušší způsob, jak nastavit TypeScript, je přes npm. Pomocí níže uvedeného příkazu můžeme nainstalovat balíček TypeScript globálně, čímž zpřístupníme kompilátor TS ve všech našich projektech:

npm install -g typescript

Zkuste kdekoli otevřít terminál a spustit tsc -v abyste zjistili, zda byl správně nainstalován.

tsc -v
Version 1.8.10

Textové editory s podporou TypeScript

TypeScript je projekt s otevřeným zdrojovým kódem, ale je vyvíjen a udržován společností Microsoft a jako takový byl původně podporován pouze na platformě Microsoft Visual Studio. V dnešní době existuje mnohem více textových editorů a IDE, které buď nativně nebo prostřednictvím zásuvných modulů nabízejí podporu pro syntaxi TypeScript, návrhy automatického doplňování, chytání chyb a dokonce i vestavěné kompilátory.

  • Visual Studio Code – další lehký editor kódu s otevřeným zdrojovým kódem od společnosti Microsoft. Je zabudována podpora TypeScript.
  • Oficiální bezplatný plugin pro vznešený text.
  • Nejnovější verze WebStorm je dodávána s integrovanou podporou.
  • Další včetně Vim, Atom, Emacs a dalších.

Kompilace do JavaScriptu

TypeScript je napsán v .ts soubory (nebo .tsx pro JSX), které nelze použít přímo v prohlížeči a je třeba je nejprve přeložit do vanilkového .js. Tento proces kompilace lze provést řadou různých způsobů:

  • V terminálu pomocí výše uvedeného nástroje příkazového řádku tsc .
  • Přímo ve Visual Studiu nebo v některém z dalších IDE a textových editorech.
  • Používání automatických spouštěčů úloh, jako je hlt.

Našli jsme první způsob, jak být nejjednodušší a nejpřátelštější pro začátečníky, takže to v naší lekci použijeme.

Následující příkaz přebírá soubor TypeScript s názvem main.ts a přeloží jej do své JavaScriptové verze main.js . Pokud main.js již existuje, bude přepsán.

tsc main.ts

Můžeme také zkompilovat více souborů najednou tak, že je vypíšeme všechny nebo použijeme zástupné znaky:

# Will result in separate .js files: main.js worker.js.
tsc main.ts worker.ts    

# Compiles all .ts files in the current folder. Does NOT work recursively.
tsc *.ts

Můžeme také použít --watch možnost automaticky zkompilovat soubor TypeScript při provedení změn:

# Initializes a watcher process that will keep main.js up to date.
tsc main.ts --watch

Pokročilejší uživatelé TypeScript mohou také vytvořit tsconfig.json soubor, který se skládá z různých nastavení sestavení. Konfigurační soubor je velmi užitečný při práci na velkých projektech se spoustou souborů .ts, protože proces poněkud automatizuje. Můžete si přečíst více o tsconfig.json v dokumentech TypeScript zde

Statické psaní

Velmi výraznou vlastností TypeScriptu je podpora statického psaní. To znamená, že můžete deklarovat typy proměnných a kompilátor se postará o to, aby jim nebyly přiřazeny nesprávné typy hodnot. Pokud jsou deklarace typu vynechány, budou automaticky odvozeny z vašeho kódu.

Zde je příklad. Každá proměnná, argument funkce nebo návratová hodnota může mít při inicializaci definován svůj typ:

var burger: string = 'hamburger',     // String 
    calories: number = 300,           // Numeric
    tasty: boolean = true;            // Boolean

// Alternatively, you can omit the type declaration:
// var burger = 'hamburger';

// The function expects a string and an integer.
// It doesn't return anything so the type of the function itself is void.

function speak(food: string, energy: number): void {
  console.log("Our " + food + " has " + energy + " calories.");
}

speak(burger, calories);

Protože TypeScript je zkompilován do JavaScriptu a ten nemá ponětí, jaké typy jsou, jsou zcela odstraněny:

// JavaScript code from the above TS example.

var burger = 'hamburger',
    calories = 300, 
    tasty = true; 

function speak(food, energy) {
    console.log("Our " + food + " has " + energy + " calories.");
}

speak(burger, calories);

Pokud se však pokusíme udělat něco nezákonného, ​​na kompilaci tsc nás upozorní, že v našem kódu je chyba. Například:

// The given type is boolean, the provided value is a string.
var tasty: boolean = "I haven't tried it yet";
main.ts(1,5): error TS2322: Type 'string' is not assignable to type 'boolean'.

Také nás upozorní, pokud funkci předáme nesprávný argument:

function speak(food: string, energy: number): void{
  console.log("Our " + food + " has " + energy + " calories.");
}

// Arguments don't match the function parameters.
speak("tripple cheesburger", "a ton of");
main.ts(5,30): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

Zde jsou některé z nejčastěji používaných datových typů:

  • Číslo – Všechny číselné hodnoty jsou reprezentovány typem čísla, neexistují samostatné definice pro celá čísla, plovoucí čísla a další.
  • Řetězec – Typ textu, stejně jako ve vanilla JS řetězce, může být obklopen „jednoduchými uvozovkami“ nebo „dvojitými uvozovkami“.
  • Booleovská hodnota – true nebo false , použití 0 a 1 způsobí chybu kompilace.
  • Jakýkoli – Proměnná tohoto typu může mít svou hodnotu nastavenou na řetězec, číslo nebo libovolnou jiná věc.
  • Pole – Má dvě možné syntaxe:my_arr: number[]; nebo my_arr: Array<number> .
  • Void – používá se u funkce, která nic nevrací.

Chcete-li zobrazit seznam všech dostupných typů, přejděte do oficiálních dokumentů TypeScript – zde.

Rozhraní

Rozhraní se používají ke kontrole typu, zda se objekt hodí do určité struktury. Definováním rozhraní můžeme pojmenovat konkrétní kombinaci proměnných a zajistit, že budou vždy ladit. Po překladu do JavaScriptu rozhraní zmizí – jejich jediným účelem je pomáhat ve fázi vývoje.

V níže uvedeném příkladu definujeme jednoduché rozhraní pro typovou kontrolu argumentů funkce:

// Here we define our Food interface, its properties, and their types.
interface Food {
    name: string;
    calories: number;
}

// We tell our function to expect an object that fulfills the Food interface. 
// This way we know that the properties we need will always be available.
function speak(food: Food): void{
  console.log("Our " + food.name + " has " + food.calories + " calories.");
}

// We define an object that has all of the properties the Food interface expects.
// Notice that types will be inferred automatically.
var ice_cream = {
  name: "ice cream", 
  calories: 200
}

speak(ice_cream);

Na pořadí vlastností nezáleží. Potřebujeme pouze, aby byly přítomné požadované vlastnosti a být správným typem . Pokud něco chybí, má špatný typ nebo se jmenuje jinak, kompilátor nás na to upozorní.

interface Food {
    name: string;
    calories: number;
}

function speak(food: Food): void{
  console.log("Our " + food.name + " has " + food.calories + " grams.");
}

// We've made a deliberate mistake and name is misspelled as nmae.
var ice_cream = {
  nmae: "ice cream", 
  calories: 200
}

speak(ice_cream);
main.ts(16,7): error TS2345: Argument of type '{ nmae: string; calories: number; } 
is not assignable to parameter of type 'Food'. 
Property 'name' is missing in type '{ nmae: string; calories: number; }'.

Toto je průvodce pro začátečníky, takže se nebudeme podrobněji zabývat rozhraními. Je toho však mnohem více, než co jsme zde zmínili, takže vám doporučujeme podívat se na dokumenty TypeScript – zde.

Třídy

Při vytváření rozsáhlých aplikací mnoho vývojářů preferuje objektově orientovaný styl programování, zejména v jazycích jako Java nebo C#. TypeScript nabízí systém tříd, který je velmi podobný systému v těchto jazycích, včetně dědičnosti, abstraktních tříd, implementací rozhraní, setterů/getterů a dalších.

Je také fér zmínit, že od poslední aktualizace JavaScriptu (ECMAScript 2015) jsou třídy nativní pro vanilla JS a lze je používat bez TypeScript. Tyto dvě implementace jsou velmi podobné, ale mají své rozdíly, TypeScript je trochu přísnější.

Pokračujeme v tématu jídla, zde je jednoduchá třída TypeScript:

class Menu {
  // Our properties:
  // By default they are public, but can also be private or protected.
  items: Array<string>;  // The items in the menu, an array of strings.
  pages: number;         // How many pages will the menu be, a number.

  // A straightforward constructor. 
  constructor(item_list: Array<string>, total_pages: number) {
    // The this keyword is mandatory.
    this.items = item_list;    
    this.pages = total_pages;
  }

  // Methods
  list(): void {
    console.log("Our menu for today:");
    for(var i=0; i<this.items.length; i++) {
      console.log(this.items[i]);
    }
  }

} 

// Create a new instance of the Menu class.
var sundayMenu = new Menu(["pancakes","waffles","orange juice"], 1);

// Call the list method.
sundayMenu.list();

Každému, kdo napsal alespoň trochu Java nebo C#, by tato syntaxe měla být dobře známá. Totéž platí pro dědictví:

class HappyMeal extends Menu {
  // Properties are inherited

  // A new constructor has to be defined.
  constructor(item_list: Array<string>, total_pages: number) {
    // In this case we want the exact same constructor as the parent class (Menu), 
    // To automatically copy it we can call super() - a reference to the parent's constructor.
    super(item_list, total_pages);
  }

  // Just like the properties, methods are inherited from the parent.
  // However, we want to override the list() function so we redefine it.
  list(): void{
    console.log("Our special menu for children:");
    for(var i=0; i<this.items.length; i++) {
      console.log(this.items[i]);
    }

  }
}

// Create a new instance of the HappyMeal class.
var menu_for_children = new HappyMeal(["candy","drink","toy"], 1);

// This time the log message will begin with the special introduction.
menu_for_children.list();

Pro podrobnější pohled na třídy v TS si můžete přečíst dokumentaci - zde.

Generika

Generics jsou šablony, které umožňují stejné funkci přijímat argumenty různých různých typů. Vytváření opakovaně použitelných komponent pomocí generik je lepší než použití any datový typ, protože generika zachovávají typy proměnných, které do nich vstupují a z nich vycházejí.

Rychlým příkladem může být skript, který přijme argument a vrátí pole obsahující stejný argument.

// The <T> after the function name symbolizes that it's a generic function.
// When we call the function, every instance of T will be replaced with the actual provided type.

// Receives one argument of type T,
// Returns an array of type T.

function genericFunc<T>(argument: T): T[] {    
  var arrayOfT: T[] = [];    // Create empty array of type T.
  arrayOfT.push(argument);   // Push, now arrayOfT = [argument].
  return arrayOfT;
}

var arrayFromString = genericFunc<string>("beep");
console.log(arrayFromString[0]);         // "beep"
console.log(typeof arrayFromString[0])   // String

var arrayFromNumber = genericFunc(42);
console.log(arrayFromNumber[0]);         // 42
console.log(typeof arrayFromNumber[0])   // number

Při prvním volání funkce jsme ručně nastavili typ na řetězec. To není vyžadováno, protože kompilátor může vidět, jaký argument byl předán, a automaticky rozhodnout, jaký typ mu nejlépe vyhovuje, jako ve druhém volání. I když to není povinné, vždy je uvádění typu považováno za osvědčený postup, protože kompilátor nemusí ve složitějších scénářích uhodnout správný typ.

Dokumenty TypeScript obsahují několik pokročilých příkladů včetně obecných tříd, jejich kombinací s rozhraními a další. Najdete je zde.

Moduly

Dalším důležitým konceptem při práci na velkých aplikacích je modularita. Rozdělení kódu do mnoha malých opakovaně použitelných komponent pomůže vašemu projektu zůstat organizovaný a srozumitelný ve srovnání s jediným 10000řádkovým souborem pro všechno.

TypeScript zavádí syntaxi pro export a import modulů, ale nedokáže zpracovat skutečné propojení mezi soubory. Chcete-li povolit externí moduly, TS se spoléhá na knihovny třetích stran:require.js pro aplikace prohlížeče a CommonJS pro Node.js. Podívejme se na jednoduchý příklad modulů TypeScript s require.js:

Budeme mít dva soubory. Jeden exportuje funkci, druhý ji importuje a volá.

exporter.ts

var sayHi = function(): void {
    console.log("Hello!");
}

export = sayHi;

importer.ts

import sayHi = require('./exporter');
sayHi();

Nyní si musíme stáhnout soubor require.js a zahrnout ho do značky skriptu – podívejte se jak na to zde. Posledním krokem je kompilace našich dvou souborů .ts. Je třeba přidat další parametr, který TypeScriptu řekne, že vytváříme moduly pro require.js (také označované jako AMD), na rozdíl od modulů CommonJS.

tsc --module amd *.ts

Moduly jsou poměrně složité a jsou mimo rozsah tohoto návodu. Pokud o nich chcete pokračovat ve čtení, přejděte do TS docs - zde.

Soubory deklarací třetích stran

Při použití knihovny, která byla původně navržena pro běžný JavaScript, musíme použít deklarační soubor, aby byla knihovna kompatibilní s TypeScriptem. Soubor deklarace má příponu .d.ts a obsahuje různé informace o knihovně a jejím API.

Soubory deklarací TypeScript jsou obvykle psány ručně, ale je velká šance, že knihovna, kterou potřebujete, již má .d.ts. soubor vytvořený někým jiným. RozhodněTyped je největší veřejné úložiště, které obsahuje soubory pro více než tisíc knihoven. Existuje také oblíbený modul Node.js pro správu definic TypeScript nazvaný Typings.

Pokud stále potřebujete napsat soubor deklarace sami, tento průvodce vám pomůže začít.

Připravované funkce v TypeScript 2.0

TypeScript je stále v aktivním vývoji a neustále se vyvíjí. V době psaní tohoto návodu je verze LTS 1.8.10, ale Microsoft již vydal beta verzi pro TypeScript 2.0. Je k dispozici pro veřejné testování a můžete si jej vyzkoušet nyní:

npm install -g [email protected]

Zavádí některé užitečné nové koncepty, jako například:

  • Příznak typů bez možnosti null, který brání některým proměnným nastavit jejich hodnotu na null nebo undefined .
  • Nový vylepšený systém pro získávání souborů deklarací přímo pomocí npm install .
  • Analýza typu řídicího toku, která zachytí chyby, které kompilátor dříve nezachytil.
  • Některé inovace v syntaxi exportu/importu modulu.

Další dlouho očekávanou funkcí je schopnost řídit tok asynchronních funkcí v async/await blok. To by mělo být dostupné v budoucí aktualizaci 2.1.

Další čtení

Množství informací v oficiálních dokumentech může být zpočátku trochu zahlcující, ale výhody jejich procházení budou obrovské. Náš tutoriál má sloužit jako úvod, takže jsme nepokryli všechny kapitoly z dokumentace TypeScript. Zde jsou některé z užitečnějších konceptů, které jsme přeskočili:

  • Jmenné prostory – zde.
  • Výčty – zde.
  • Pokročilé typy a kryty typů – zde.
  • Zápis JSX v TypeScript – zde.

Závěr

Doufáme, že se vám tento tutoriál líbil!

Máte nějaké myšlenky na TypeScript a uvažovali byste o jeho použití ve svých projektech? Neváhejte a zanechte níže komentář!


No