Se ha denunciado esta presentación.
Se está descargando tu SlideShare. ×

Type script - advanced usage and practices

Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Cargando en…3
×

Eche un vistazo a continuación

1 de 25 Anuncio

Más Contenido Relacionado

Presentaciones para usted (20)

Similares a Type script - advanced usage and practices (20)

Anuncio

Más reciente (20)

Type script - advanced usage and practices

  1. 1. TypeScript Advanced usage and practices https://github.com/ivanderk/a-bit-more-advanced-typescript
  2. 2. This Ain´t your Java
  3. 3. TypeScript the language as presented orginally 3
  4. 4. TypeScript the language in 2017 ES5.1 EcmaScript 2017 TypeScript 2.3 Environment
  5. 5. Know your environment: the tool chain Programming in EcmaScript 2015+ and TypeScript is quite unlike programming in JavaScript. With the latter in theory you could use just the browser and Notepad. Browser support for EcmaScript is still limited and absent in case of TypeScript. So you will need a compiler and a whole tool chain to work with these languages. And more: in practice you will need to know, and know well:  Visual Studio Code (or another IDE like Webstorm or Atom)  a whole series of plugins for the IDE  the TypeScript compiler (tsc, ts-node) (or Babel & Flow)  Node inspector (V8 debugger) and/or Chrome Developer Tools (and corresponding tools)  node.js  TSLint (“linter” or style and error checker)  Yarn, npm (package management)  Mocha, chai (for testing)  Git (Source Code Version Control)  TypeDoc (Documentation Tool)
  6. 6. Learn ES201x
  7. 7. let is the new var Use let instead of var Block scope vs function scope No more “hoisting” //compiles fine function functionscope(){ for(i=0;i < 10; i++){ console.log(i) } if (true){ var i = 10000 } console.log(i) } //gives error TS2304: Cannot find name 'i'. function blockscope(){ //let i; for(i=0;i < 10; i++){ console.log(i) } if (true){ let i = 100000 } console.log(i) } functionscope() blockscope() src: letisthenewvar.ts
  8. 8. let is the new var; fixes problem with closures Using let fixes a longstanding problem with closures block scoped references captured in a closure will maintain the value at the moment of capture That is NOT the case with var (the reference will point to the last value it was set to) for(var j= 0; j < 10; j++){ setTimeout(()=> console.log(`setTimeout with var: ${j}`),100) } for(let k= 0; k < 10; k++){ setTimeout(()=> console.log(`setTimeout with let: ${k}`),100) } src: letisthenewvar.ts
  9. 9. let is the new var (and so is const) Use const when you want to denote immutability of a reference (the “variable”). Use readonly for object properties. Notice that objects and arrays are not const. Only their references. Use Object.freeze or Immutable.js (a library) for this. No compile time, type level, support for nested immutability const co = 100 //gives error TS2540: Cannot assign to 'co' because it is a constant or a read-only property. //co = 1000 const co2 = {a: 100} co2.a = 10000000000000000 console.log(co2) Object.freeze(co2) //RUN-TIME ERROR: TypeError: Cannot assign to read only property 'a' of object '#<Object>' co2.a = 0 src: letisthenewvar.ts
  10. 10. Modules export function hello() { return 'Hello World!' } export function hola(){ return 'Hola mundo!' }TypeScript and ECMAScript 201x have a concept of modules. Any file containing a top-level import or export is considered a module. Modules are executed within their own scope, not in the global scope; this means that variables, functions, classes, etc. declared in a module are not visible outside the module unless they are explicitly exported using one of the export forms. Conversely, to consume an export (variables, etc.) from a different module, it has to be imported using one of the import forms. Examples can be found on the right: import { hello } from '../app/services'; import { hola as spanishhello } from '../app/services'; import * as greetings from '../app/services'; import Msg from '../app/defaultservices' console.log(hello()) console.log(spanishhello()) console.log(greetings.hello()) let msg = new Msg() console.log(msg.hola()) export default class { hello() { return 'Hello World!' } hola(){ return 'Hola mundo!' } } src: testimports.ts services.ts defaultservices.ts
  11. 11. Unit Testing Unit testing in TypeScript in general takes the form of automatic testing of TS modules together with associated control data to determine whether these modules work excepted. With mocha as testing framework or test runner, and chai and assertion library, it is easy to integrate (a form of) TDD or BDD within each TS project. import { expect } from "chai" // if you used the '@types/mocha' method to install mocha type definitions, uncomment the following line import "mocha" import { hello } from "../app/services" describe("Hello function", () => { it("should return hello world", () => { const result = hello() expect(result).to.equal("Hello World!") }) }) src: test.ts
  12. 12. The TypeScript Type System
  13. 13. TypeScript´s Type System The type system in TypeScript is designed to be optional so that your JavaScript is TypeScript. TypeScript does not stop generating JavaScript code in the presence of type errors, allowing you to progressively update your JS to TS. But that does mean that TypeScript is not “safe” But --noEmitOnError flag prevents generating JavaScript code when there are Type errors Therefore: Types are annotations; they don´t “exist” run-time (type erasure) let foo = {}; foo.bar = 123; // Error: property 'bar' does not exist on `{}` console.log(foo.bar) foo.baz = "ABC" // Error: property 'baz' does not exist on `{}` console.log(foo.baz) c src: typesdontexist.ts
  14. 14. Type annotation syntax Type annotations are optional They can be added after any expression Classes and interface are first class citizens within the type system (but be careful for comparisons with Java; see structural typing) Function parameters and the function result are typed. But note that functions themselves also have a type. The type keyword can be used to declare a type alias let x : number x = 10 let y : number = 10 interface Named { name: string } class M implements Named{ name: string constructor(name:string){ this.name = name } } let m : Named = new M("Jorge") console.log(m.name) let double = function(a: number): number{ return a + a } type Doubler = (a:number) => number let doStuff = function(callback: Doubler){ //do LOTS of stuff console.log(callback(100)) console.log(callback(100)) console.log(callback(100)) } doStuff(double) src: typeannotations.ts
  15. 15. Type inference let fullName = `Perico Palotes` let age = 37 let sentence = `Hola, me llamo ${ fullName }` console.log(sentence) // error TS7006: Parameter 'name' implicitly has an 'any' type. //let englishName = function(name){ let englishName = function(name : any){ let sentence = `Hello, my name is ${ name }` console.log(sentence) } englishName(fullName) englishName(1000) // Hello, my name is 1000 let englishName2 = function(name: string){ let sentence = `Hello, my name is ${ name }` console.log(sentence) } // englishName2(1000) Compile error In modern statically typed programming languages like TypeScript, it is not necessary to always declare the type of a variable. The compiler can infer the type of the expression. In TypeScript the type of function parameters without type annotations is inferred to be of type any. This can result in errors when compile flag –noImplicitAny is set src: typeinference.ts
  16. 16. --strict (TypeScript 2.3) flag Meaning --alwaysStrict Parse in strict mode and emit "use strict" for each source file --noImplicitThis Raise error on this expressions with an implied any type. --strictNullChecks Strict null checking mode, the null and undefined values are not in the domain of every type and are only assignable to themselves and any (the one exception being that undefined is also assignable to void). --noImplicitAny Raise error on expressions and declarations with an implied any type. --noImplicitReturns Report error when not all code paths in function return a value. … more … TypeScript supports a whole series of “compiler flags” which can be set in tsconfig.json. From version 2.3 on, all flags related with “strict” compilation can be set in with the –strict flag. In 2.2 and below the flags need to be set individually. src: strict.ts
  17. 17. Type inference, arrays and Tuples let arr1 = [0,1,2] //Not inferred to be a Tuple, but rather an array of elements of two possible types: number OR String let arr2 = [500,"Internal Server Error"] console.log(arr2) //compile error //let tuple : [number, string] = arr2 type HTTPError = [number, string] let error1 : HTTPError = [500,"Internal Server Error"] //Type Asseryion (not "cast") let error2 = [500,"Internal Server Error"] as HTTPError console.log(error1, error2) Tuple types allow you to express a type, effectively an array of fixed size, where the type of a fixed number of elements is known, but need not be the same. As the literal syntax for Arrays and Tuples are identical, Tuple types cannot be inferred correctly. src: typeinference.ts
  18. 18. Contextual inference Type inference also works in "the other direction" in some cases in TypeScript. This is known as "contextual typing". Contextual typing occurs when the type of an expression is implied by its location. import { readFile } from "fs" readFile("d:/tmp/data.txt", function(err,buf){ console.log(buf.toString()) }) src: contextual.ts
  19. 19. Best practice DRY and don´t be verbose: use type inference let s1 = "lala" /*NOT*/ let s2: string = "lala" Avoid the implicit usage of any --noImplicitAny Type the parameters of your own non call-back functions. Optionally type the return value of the function function translate(text:string):string { return `¿Eh? ¿Que signifique '${text}'?` }
  20. 20. Destructuring let node = { type: "Identifier", id: "foo" }; let { type, id } = node console.log(type) // "Identifier" console.log(id) // "foo” // compile error when --noImplicitAny is set // alternative: // let showName = function( { id } : {id:string} ){ let showName = function( { id } ){ console.log(id) } showName(node); // "foo” ECMAScript 201x simplifies data access by adding destructuring, which is the process of breaking down a data structure into smaller parts. This is extremely powerful and useful. And it´s an essential, integral part of the core features of the language (modules). But be careful, because of TypeScript´s type system, destructuring can be a bit different in “feel” between the two languages. src: destructuring.ts
  21. 21. Destructuring: arrays and nesting Array destructing is syntactically different from Object destructuring but follows the same principle. The remaining items in a list can be caught in a variable for the using the syntax ...name Complex destructuring patterns can arise with nested objects, Tuples and arrays. let input = [1, 2]; // create NEW variables first and second let [first, second] = input; console.log(first); // outputs 1 console.log(second); // outputs 2 // swap variables [first, second] = [second, first]; //remaining items in a list using the syntax ...name : let [firstelement, ...remainder] = [1, 2, 3, 4]; console.log(firstelement); // outputs 1 console.log(remainder); // outputs [ 2, 3, 4 ] //Nested destructuring of Tuples/arrays. Only have a binding for the named item let justanarray : [string, boolean, number[]] = ["data",true,[3,4]] let [,,[,elem2]] = justanarray console.log(`Nested element in array ${elem2}`) // outputs 4 let nestedobject = {anumber: 100, nested: {deep: "ok"}} let {nested: {deep}} = nestedobject //compile error: only names "on the right" of the expression are declared //console.log(nested) console.log(deep) //variable renaming; confusing syntax! let {nested: {deep: deepest}} = nestedobject console.log(deepest) src: destructuring.ts
  22. 22. Structural typing Type compatibility in TypeScript is based on structural (sub)typing. Structural typing is a way of relating types based solely on their members. This is in contrast with nominal type systems like that of C# and Java interface Named { name: string; } class Person { // no ‘implements’ name: string; constructor(name:string){ this.name = name } //constructor(public name: string){} } let p: Named; // OK, because of structural typing p = new Person("Hagard"); console.log(p) // also with anonymous objects p = { name: "Olaf" } console.log(p) src: typecompat.ts
  23. 23. Type inference with assignment & declarations There is a difference in the behaviour of type inference between declarations (“let”) with their corresponding initializers and assignment. In the example assignment works but the variable initializer must exactly match the structure of Named interface Named { name: string; } let p: Named; // also with anonymous objects let o = { name: "Olaf" , surname: "Leifson"} p = o; console.log(p) // compile error //let n : Named = { name: "Olaf" , surname: "Leifson"} src: typecompat.ts
  24. 24. Decorators A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter. Decorators use the form @expression, where expression must evaluate to a function that will be called at runtime with information about the decorated declaration. It is a form of meta-programming which follows the model as set by Decorators in Python, i.e. they are actively executing functions, rather than the model followed by Annotations in Java (objects as passive meta-data) The application of Decorators is an “experimental” feature of EcmaScript / TypeScript. It may change but it is unlikely to disappear (as many important libraries like Angular are already depending on it). Decorators are an advanced topic and extremely powerful but also very “magical”, complex and therefore fraught with danger. Use with care. function log(target: any, key: string, value: any) { return { value(...args: any[]) { const result = value.value.apply(this, args) console.log(`method: '${key}' called with arguments '${args}' and with result: '${result}'`) return result } } } class Demo { @log public say(...args: string[]) { console.log("Inside say with arguments: ", args) return 100 } } let d = new Demo() d.say("Booh", "Lala") d.say("Bah") src: decorators.ts
  25. 25. What´s left: Async – await Symbols Iterators & generators Discrimitated Unions Mixins and much more …

×