Typescript w Sealiousie?

open-source
sealious

#1

Po ostatnich dużych refactorach Sealiousa zauważyłem, że bardzo często zostawiam błędy w postaci “ta funkcja przyjmuje o jeden argument mniej, a go nie usunąłeś”, lub “podałem argumenty w złej kolejności”.

Sprowokowało mnie to do zastanowienia się, czy nie byłoby fajnie zacząć korzystać z TypeScripta. Dokonuje on statycznej analizy kodu i wychwytuje takie rzeczy, ale nie narzuca się za bardzo i czyni typowanie opcjonalnym.

Jestem ciekaw Waszych opinii :slight_smile:


#2

Tak jak wspomniałem - ta myśl już zagościła w mojej głowie i uważam, że to dobry pomysł. Zrobię mały research w temacie TypeScript vs Flow w wolnej chwili i podziele się :slight_smile:


#3

Używam w Angularze aka Angulaszu 5 i bardzo sobie chwalę :slight_smile: stack tslint + prettier współgrają do tego doskonale.


#4

Zastanawiam się, jak trzeba sobie poradzić z TypeScriptem na backendzie - bo trzeba użyć preprocessora wtedy, prawda? :thinking:


#5

Bez znaczenia gdzie to zostanie użyte potrzebny jest kompilator który skompliuje pliki TypeScript do regularnego JavaScriptu. Np. w @angular-cli jest watcher z webpacka który rekompiluje wszystkie zmiany w locie i działa to bardzo płynnie.


#6

Primo, pytanie na ile można w nim korzystać z ficzerów ES6/7.
Secundo, pytanie czy to “nie narzuca się za bardzo” nie okaże się jednak za bardzo.

Chyba ja bym się wstrzymał z dodaniem tego do Sealiousa i zrealizował na tym jakiś inny, mniejszy projekt - to dałoby nam dobry ogląd sytuacji przy niewielkim koszcie jeżeli TS okazałby się jednak zbyt wkurzający.


#7

Myślę, że warto spróbować najpierw gdzieś indziej. Jestem też ciekaw, jakie wnioski przyniesie risercz Bartka :wink:

Póki co i tak musimy sobie radzić assertami :stuck_out_tongue:


#8

@piotr-ptaszynski możesz korzystać z ES6/7 - wystarczą odpowiednie transpilery


#9

@kuba-orlik mój błąd odnośnie kompilatora, nie jest potrzebny np. https://github.com/TypeStrong/ts-node


#10

hmm tylko wtedy wymagamy, aby cała aplikacja była odpalana za pomocą ts-node, prawda? Trochę wirusowe mi się to wydaje, chociaż i tak odpalamy apki w dockerowo izolowanym środowisku, więc who cares :stuck_out_tongue:


#11

Warte przetestowania, zawsze można kompilować - bo produkcyjnie i tak jsowy plik wynikowy będzie szybszy (chyba?). :thinking:


#12

Jeden z krótkich przykładów dlaczego podoba mi się TypeScript, mam sobie taki komponent i metodę add:

// heroes.component.ts

import { Hero } from "../hero";
import { HeroService } from "../hero.service";

export class HeroesComponent{
	constructor(private heroService: HeroService) {}

	add(name: string): void {
		const newHero = new Hero();
		newHero.name = name;
		this.heroService.addHero(newHero).subscribe();
	}

// Parametr dla `this.heroService.addHero` można zapisać krócej po prostu ` { name } `
// albo dodatkowo z użyciem słowa kluczowego `as` co znaczy mniej więcej tyle że
// mówimy do type checkera traktuj to coś `{ name }` jako obiekt innego typu - typu `Hero`

	add2(name: string): void {
		this.heroService.addHero({ name } as Hero).subscribe();
	}

}

Automatycznie dostaniemy błąd jeżeli podamy obiekt innego typu ponieważ w serwisie ta metoda ma przyjąć zmienną typu Hero:

// hero.service.ts
addHero(hero: Hero): Observable<Hero> {
	return this.http
		.post<Hero>(this.heroesUrl, hero)
		.pipe(
			tap((hero: Hero) => this.log(`added hero w/ id=${hero.id}`)),
			catchError(this.handleError<Hero>("addHero"))
		);
}

Oczywiście moglibyśmy zainicjonalizować obiekt Hero bezpośrednio jako argument do metody addHero komponentu heroesComponent przez new Hero(name), ale definicja modelu Hero wygląda następująco (nie mamy konstruktora):

// hero.ts
export class Hero {
	id: number;
	name: string;
}

Syntax TypeScriptu i całe typowanie daje Nam dużo przydatnych udogodnień przez to kod jest krótszy i moim zdaniem nie mniej czytelny. :slight_smile:


#13

Rozmawialiśmy trochę o tym offline z Bartkiem i napotkaliśmy jeden problem - TypeScript nie robi sprawdzania typów w trakcie runtime’u. Co powoduje, że musimy wciąż robić ręczną walidację typów, co jest dosyć upierdliwe. Znalazłem kilka alternatyw:

Musimy ustalić, jakie problemy chcemy rozwiązywać. Moim zdaniem są to:

  1. Ręczne sprawdzanie typów argumentów i pisanie treści błędów w assert-ach jest upierdliwe. Aby rozwiązać ten problem potrzebujemy sprawdzania typów w trakcie runtime’u.
  2. Patrząc na kod funkcji jest czasem trudno odgadnąć, w jakiej postaci powinna otrzymywać ona argumenty. Ten problem rozwiąże dowolna notacja określająca typy argumentów itp. Możliwość statycznej analizy ułatwiającej integrację z IDE jest mile widziana, ale moim zdaniem nie jest konieczna.
  3. Trudno jest wykryć wszystkie niekompatybilne ze sobą wywołania funkcji, gdy robimy np. refaktor.. Tutaj statyczna analiza jest bardzo przydatna.

#15

Jestem zdecydowanie za ^_^. Używałem w angularze i pisało się o wiele przyjemniej mogąc deklarować typy.


#16

A jakiego typowania używałeś? Typescript, flow?


#17

Typescript


#18

Jeszcze jest coś takiego: ts-runtime

Z tym deno to zastanawiam się jak wygląda wydajność i jak wygląda kwestia paczek npmowych. Niby pracuje nad tym jeden z twórców Node więc to raczej poważny projekt.

EDIT:
Ale ogólnie jestem za pójściem w tę stronę