Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
txs:peertube_a18:concepts_typescript [2020/02/06 15:31] – ↷ Page déplacée de txs:peertube-a18:concepts_typescript à txs:peertube_a18:concepts_typescript qduchemi | txs:contrib:peertube_a18:concepts_typescript [2020/09/16 11:24] (Version actuelle) – modification externe 127.0.0.1 | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ====== Concepts centraux de TypeScript ====== | ||
+ | |||
+ | PeerTube est développé à l'aide de [[http:// | ||
+ | |||
+ | TypeScript offre des possibilités qui reposent sur les concepts centraux suivants. | ||
+ | |||
+ | ===== Le static-typing ===== | ||
+ | Le premier apport de TypeScript, ce qui lui vaut son nom, est le typage. | ||
+ | |||
+ | ==== Variables ==== | ||
+ | Il est possible d' | ||
+ | |||
+ | Lors de l' | ||
+ | |||
+ | Une déclaration de variables se fait comme suit : | ||
+ | <code javascript> | ||
+ | var page: number = 7; // annotation de type | ||
+ | var completeVideoDescription: | ||
+ | var remoteServerDown = true; // boolean (implicite) | ||
+ | var joker: any; | ||
+ | var joker2; // any | ||
+ | </ | ||
+ | |||
+ | ==== Fonctions ==== | ||
+ | On peut indiquer le **type du retour** d'une fonction : | ||
+ | <code javascript> | ||
+ | function helloWorld(): | ||
+ | return "Hello World"; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Intérêt ==== | ||
+ | Cette possibilité de déclarer explicitement le type d'une variable est nommée **// | ||
+ | |||
+ | Mais l' | ||
+ | |||
+ | ===== Concepts de l' | ||
+ | |||
+ | TypeScript complète JavaScript avec des éléments de la [[https:// | ||
+ | |||
+ | |||
+ | ==== Les interfaces ==== | ||
+ | Supposons qu'on ait un objet '' | ||
+ | <code javascript> | ||
+ | interface User { | ||
+ | firstName: string; | ||
+ | lastName: string; | ||
+ | } | ||
+ | |||
+ | function greeter(user: | ||
+ | return " | ||
+ | } | ||
+ | |||
+ | let user = { firstName: " | ||
+ | |||
+ | document.body.innerHTML = greeter(user); | ||
+ | </ | ||
+ | |||
+ | Le // | ||
+ | * on peut ne pas déclarer explicitement que '' | ||
+ | * '' | ||
+ | |||
+ | On trouvera souvent ces interfaces déclarées en haut des fichiers de code. | ||
+ | |||
+ | A la différence d'une structure en C, **une interface n'est pas instanciable**, | ||
+ | |||
+ | **Une interface n'est pas une classe**. Ce que fait l' | ||
+ | |||
+ | ---- | ||
+ | |||
+ | Dans le code de **PeerTube**, | ||
+ | |||
+ | ==== Les classes ==== | ||
+ | |||
+ | === Déclaration === | ||
+ | |||
+ | Les classes en TypeScript se déclarent comme dans l' | ||
+ | <code javascript> | ||
+ | class VideoWatchComponent { | ||
+ | //// attributs | ||
+ | player: videojs.Player | ||
+ | completeDescriptionShown = false | ||
+ | completeVideoDescription: | ||
+ | shortVideoDescription: | ||
+ | videoHTMLDescription = '' | ||
+ | ... | ||
+ | |||
+ | //// constructeur | ||
+ | constructor( | ||
+ | constr_videoHTMLDescription: | ||
+ | private elementRef: ElementRef, | ||
+ | private changeDetector: | ||
+ | private route: ActivatedRoute, | ||
+ | private router: Router, | ||
+ | ... | ||
+ | ) { | ||
+ | this.videoHTMLDescription = constr_videoHTMLDescription; | ||
+ | | ||
+ | |||
+ | //// méthodes | ||
+ | // un getter : | ||
+ | get user () { | ||
+ | return this.authService.getUser() | ||
+ | } | ||
+ | | ||
+ | // un setteur : | ||
+ | setLike () { | ||
+ | if (this.isUserLoggedIn() === false) return | ||
+ | if (this.userRating === ' | ||
+ | // Already liked this video | ||
+ | this.setRating(' | ||
+ | } else { | ||
+ | this.setRating(' | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | // une autre fonction de la classe : | ||
+ | showMoreDescription () { | ||
+ | if (this.completeVideoDescription === undefined) { | ||
+ | return this.loadCompleteDescription() | ||
+ | } | ||
+ | |||
+ | this.updateVideoDescription(this.completeVideoDescription) | ||
+ | this.completeDescriptionShown = true | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Cet exemple est basé sur la classe déclarée dans le fichier '' | ||
+ | |||
+ | Une déclaration de classe se structure donc par des **attributs** (variables définies sans le mot clé '' | ||
+ | |||
+ | Attributs et méthodes peuvent être de 4 types différents : | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | === Instanciation === | ||
+ | |||
+ | Pour instancier la classe déclarée précédemment, | ||
+ | <code javascript> | ||
+ | var ma_classe = new VideoWatchComponent(" | ||
+ | </ | ||
+ | Cette instanciation permet grâce au constructeur de d' | ||
+ | * L' | ||
+ | <code javascript> | ||
+ | ma_classe.videoHTMLDescription; | ||
+ | </ | ||
+ | * L' | ||
+ | <code javascript> | ||
+ | ma_classe.getVideoHTMLDescription(); | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Héritage === | ||
+ | |||
+ | De pair avec la notion de classe, TypeScript implémente la notion d' | ||
+ | |||
+ | Dans le fichier ''/ | ||
+ | <code javascript> | ||
+ | class VideoTrendingComponent extends AbstractVideoList { | ||
+ | titlePage: string | ||
+ | | ||
+ | ... | ||
+ | | ||
+ | getVideosObservable (page: number) { | ||
+ | const newPagination = immutableAssign(this.pagination, | ||
+ | return this.videoService.getVideos(newPagination, | ||
+ | } | ||
+ | | ||
+ | ... | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | Cette nouvelle classe '' | ||
+ | |||
+ | TypeScript permet un **pseudo-héritage multiple** en combinant classes et interfaces. Grâce au mot-clé '' | ||
+ | <code javascript> | ||
+ | class VideoWatchComponent implements OnInit, OnDestroy { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Comme dans d' | ||
+ | |||
+ | Enfin, comme en JavaScript, le mot-clé '' | ||
+ | |||
+ | |||
+ | ===== La modularité ===== | ||
+ | |||
+ | TypeScript introduit différentes techniques permettant de concevoir des applications modulaires et de grandes tailles, à l' | ||
+ | |||
+ | Lorsque l'on déclare une variable, une classe, une fonction, //etc//. dans un fichier, celle-ci n'est visible et utilisable par un autre fichier qu'à la condition d' | ||
+ | |||
+ | |||
+ | ==== Export ==== | ||
+ | Il existe deux façons, combinables, | ||
+ | * La mention '' | ||
+ | <code javascript> | ||
+ | export interface Video { | ||
+ | id: number | ||
+ | uuid: string | ||
+ | createdAt: Date | string | ||
+ | updatedAt: Date | string | ||
+ | publishedAt: | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | * En rajoutant une ligne à cet effet après la déclaration de l' | ||
+ | <code javascript> | ||
+ | /* export -> non nécessaire */ interface Video { | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | export { Video }; | ||
+ | // ou | ||
+ | export { Video as interfVideo }; // pour renommer l' | ||
+ | </ | ||
+ | |||
+ | Ces deux techniques sont utilisées dans le code de PeerTube de façon redondante. Le mot-clé '' | ||
+ | <code javascript> | ||
+ | export * from ' | ||
+ | export * from ' | ||
+ | export * from ' | ||
+ | ... | ||
+ | export * from ' | ||
+ | export * from ' | ||
+ | export * from ' | ||
+ | export { VideoConstant } from ' | ||
+ | </ | ||
+ | | ||
+ | | ||
+ | ==== Import ==== | ||
+ | L' | ||
+ | <code javascript> | ||
+ | import { VideoModel } from ' | ||
+ | </ | ||
+ | On peut, de même qu' | ||
+ | <code javascript> | ||
+ | import { ScopeNames as VideoScopeNames, | ||
+ | </ | ||
+ | Il est également possible d' | ||
+ | <code javascript> | ||
+ | import * as Sequelize from ' | ||
+ | |||
+ | ... | ||
+ | const escapedSearch = VideoModel.sequelize.escape(options.search) | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | ===== Sources ===== | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | |||
+ | |||
+ | |||