Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Microsoft Ignite The Tour Paris - A TypeScript journey!

Microsoft Ignite The Tour Paris - A TypeScript journey!

Presentation on TypeScript made with Félix Billon, Paul Souche and Terance Moussoki

Sylvain PONTOREAU

November 13, 2019
Tweet

More Decks by Sylvain PONTOREAU

Other Decks in Programming

Transcript

  1. A TypeScript journey Microsoft Ignite The Tour - Paris 2019

    Sylvain Pontoreau Terance Moussoki Paul Souche Félix Billon
  2. @ParisTypeScript Who we are and how to contact us @spontoreau

    @MoussokiT @lsagetlethias @felix_billon @paulsouche
  3. Types are an advantage • Errors at compile time instead

    of runtime • Code readability, maintenability & scalability • Less bugs (average: -15%) • IDEs (Autocomplete, code inspection, refactoring) • Type inference const hello = "Hello world!";
  4. Type capabilities • Primitive types: number, string, boolean • Special

    types: any, void, unknow • Classes (constructor, abstract, inheritance, access modifiers, …) • Interface (can be used by TypeScript to check object structure) • Type alias const value: number = 1; type one = 1;
  5. But take care • Any everywhere isn’t a solution (you’re

    doing JavaScript…) • Nominal typing • Structural typing • So TypeScript !== C#, Java • Strict mode is recommanded
  6. Generic An exemple with the Factory pattern: abstract class Rocket

    { constructor( public readonly boosters : number ) { } abstract launch() : void; } class RocketFactory<T extends Rocket> { ctor: new (boosters: number) => T; constructor(ctor: new (boosters: number) => T) { this.ctor = ctor; } create(boosters: number): T { return new this.ctor(boosters); } }
  7. Generic Generic & type system: // type alias type Rocket

    = { id: number; model: string; boosters: number; }; // Mapped type type Partial<T> = { [K in keyof T]?: T[K]; }; const e: Partial<Rocket> = { }; // Conditional type Exclude<T, U> = T extends U ? never: T; type Keys = Exclude<keyof Rocket, "id">; You will have more information about that in Part 2
  8. Decorators Currently experimental! Can be apply on: • Classes •

    Methods • Properties • Parameters TC 39: Draft "experimentalDecorators": true, "emitDecoratorMetadata": true,
  9. Decorators const track: MethodDecorator = ( target: any, key: string

    | symbol, descriptor: PropertyDescriptor ) => { const calledFunction = descriptor.value; const newFunction = (this: any, ...args:any[]) { Telemetry.Track({ className: target.constructor.name, methodName: key.toString(), parameters: args }); return calledFunction.apply(target, args); }; descriptor.value = newFunction; return descriptor; };
  10. Decorators Usage: class Rocket { orientation: Vector3 = new Vector3(0.0,

    0.0, 1.0); @track correctPath(vector: Vector3) { this.orientation.add(vector); } } const rocket = new Rocket(); // Telemetry will track: // {"className":"Rocket","methodName":"correctPath","parameters":{"0":{"x":0.1,"y":0.2,"z":0}}} rocket.correctPath(new Vector3(0.1, 0.2, 0.0));
  11. Summary • Advanced Types (12.5 min) Paul ◦ never /

    unknown / type alias / as const ◦ literal / index types ◦ union | Intersection ◦ type guards ◦ mapped / conditional types • Strict mode (15 min) Félix ◦ strictNullChecks ◦ noImplicitAny ◦ noImplicitThis ◦ strictFunctionTypes ◦ alwaysStrict ◦ strictBindCallApply ◦ strictPropertyInitialisation
  12. Summary • Compiler (12.5 min) Paul ◦ declarations / declarationDir

    ◦ listFiles / noEmit ◦ allowJs / checkJS ◦ noEmitHelpers / importHelpers ◦ lib / typeRoots / types resolution ◦ moduleResolution ◦ baseUrl / paths ◦ esModuleInterop / allowSyntheticDefaultImports • TypeScript 3.7 (5 min) Félix ◦ Tc39 features ◦ + ts features
  13. Never / unknown / type alias / as const (1

    / 4) link Type never represents the type of values that never occur - Raised exceptions - Infinite Loops - Conditional types fallback
  14. Never / unknown / type alias / as const (2

    / 4) link Type unknown acts like any but type safely : it must be casted - Used in type guards - Useful when type is unnecessary (proxy)
  15. Never / unknown / type alias / as const (3

    / 4) link Type alias is a “type variable” - Shorten long combinaison of union, intersection, mapped types
  16. Never / unknown / type alias / as const (4

    / 4) link Cast as const returns a readonly literal type
  17. Literal / index types (1 / 2) link A literal

    type defines the exact value of a type it can be string, numeric or even object (as const)
  18. Literal / index types (2 / 2) link With index

    types the compiler checks code that use dynamic property names
  19. Union / Intersection (1 / 2) link An union type

    is actually the “intersection” of its members
  20. Union / Intersection (2 / 2) link An intersection type

    is actually the “union” of its members
  21. Type Guards (1 / 3) link A type guard is

    a runTime check that can be interpreted in control flow Built-in type guards : typeof, Array.isArray, instanceOf
  22. Type Guards (2 / 3) link Most of the time

    we use it with a literal type
  23. Mapped / Conditional types (1 / 6) link A mapped

    type is a “function type” that takes a type and map it thanks to indexable types
  24. Mapped / Conditional types (3 / 6) link A conditional

    type selects one of two possible types based on a condition
  25. Strict mode ? - one of the most important option

    ! - compilation’s option that enforce strict typings - master option’s that activate some sub-option : - strictNullChecks - noImplicitAny - noImplicitThis - strictFunctionTypes - alwaysStrict - strictBindCallApply - strictPropertyInitialisation
  26. How activate Strict mode - On new project use tsc

    --init, strict option will be activated - In tsconfig.json file, strict is deactivated by default - On existing project it can be adopted incrementally :
  27. --strictNullChecks (1/4) - By default, null and undefined are included

    in other type in imlipicit way - --strictNullChecks make them apart type, it needs to be explicit
  28. --strictNullChecks (3/4) - To handle null and undefined you can

    use : - Union type : link - Type Guard : link
  29. --strictNullChecks (4/4) link - In some specific case you can

    use non-null assertion operator “!” - Be careful with non-null assertion operator cause you enforce TypeScript’s compiler behavior.
  30. --noImplicitAny link - any is a dangerous type and he

    can be : - explicit : you wrote any - implicit : use by TypeScript’s compiler when type is not explicit and it can’t infer it. - --noImpliciteAny raised error when second case appear
  31. --noImplicitThis (1/2) link - TypeScript’s compiler try to infer this

    in function’s body - If compiler can’t infer it, --noImplicitThis will raised an error
  32. --noImplicitThis (2/2) link - You can enforce the type of

    this by typings it as a first argument in a function
  33. --strictPropertyInitialisation (1/2) link - when activate, the type checker verifies

    that each class’s property : - has a type that include undefined - has been initialized during déclaration - has been initialized in the constructor - Exemple
  34. --strictPropertyInitialisation (2/2) link - In some specific case you can

    use definite assignment assertion operator “!”
  35. declarations / declarationDir (1 / 1) - --declarations is a

    flag to output or not the declarations (default false) - It is available through the cli - Used when need to publish declaration for a consumer - --declarationDir is the relative path where to output declarations files (same as --outDir if not provided) - It is available through the cli - To publish the code on a registry use “types” key in package.json to refer to the declarations entry (index.d.ts) by default
  36. listFiles / noEmit (1 / 1) - --listFiles is a

    flag to output the files part of the transpilation (default false) - It is available through the cli - Useful for debug - --noEmit is a flag to not emit any file but just typecheck the code (default false) - It is available through the cli - Useful for scripts executed by ts-node or tests
  37. allowJs / checkJs (1 / 1) - --allowJs is a

    flag to allow to import JavaScript files (default false) - It is available through the cli - No need for this flag for JavaScript in node_modules (TypeScript will resolve declarations) - --checkJs is a flag to try type checking on JavaScript files - It is available through the cli - Same as @ts-check in a JavaScript file
  38. noEmitHelpers / importHelpers (1 / 2) - --noEmitHelpers is a

    flag to not Emit helpers functions when targeting old browsers or node versions - It is available through the cli - async / await is available in es3
  39. noEmitHelpers / importHelpers (2 / 2) - --importHelpers is a

    flag to Emit tslib imports when targeting old browsers - It is available through the cli - Need tslib as dependency
  40. - --lib is a list of lib files to includes

    during transpilation - It is available through the cli - It lists all ecmaScript features available at runTime - Old browser => lib: [“dom”, “es5”] - New browser (or polyfilled) => lib: [“dom”, “esnext”] - Node => lib: [“esX”] (X follows the target version of node) lib / typeRoots / types (1 / 2)
  41. - --typeRoots is a list of relative paths to resolve

    dependencies declarations (default node_modules/@types) - It is available through the cli - No need if dependency handle it’s own definitions - Can be a local directory too - --types is a list of folders names in the typeRoots folder to include during the transpilation - It is available through the cli - Useful to exclude declarations for tests in your code for example lib / typeRoots / types (2 / 2)
  42. moduleResolution (1 / 5) - --moduleResolution is a string to

    configure compiler modules lookup - Two values: “classic” or “node” - Different resolution in case of relative or non relative imports
  43. - --baseUrl is a relative path to set the modules

    root - It is available through the cli - It sets the “/root/” path in the previous examples - Used when a part of the code base is published on a registry - --paths is a map of aliases (non-relative) / relative paths to resolve modules locally - It is not available through the cli - If relative path refers to a ts file, it will be part of the transplication not if it refers to a d.ts file - Same for TypeScript files resolved in the node_modules folder - Do not publish TypeScript files (.ts) on the registry => declarations only baseUrl / paths (1 / 1)
  44. - --esModuleInterop is a flag to emit “__importStart” and “__importDefault”

    helpers (babel compatibility). it activates -- allowSyntheticDefaultImports esModuleInterop / allowSyntheticDefaultImports (1 / 2)
  45. - --allowSyntheticDefaultImports is a flag to allow default imports even

    if declaration has no default export esModuleInterop / allowSyntheticDefaultImports (2 / 2)
  46. What’s new in 3.7 : Null Coalescing link - Same

    as || but don’t treat NaN, 0 and empty string as falsy value.
  47. What’s new in 3.7 : Optional Chaining link - Same

    as && but don’t treat NaN, 0 and empty string as falsy value.
  48. What’s new in 3.7 - Optional Chaining - Nullish Coalescing

    - Assertion Functions - Better Support for never-Returning Functions - (More) Recursive Type Aliases - --declaration and --allowJs - The useDefineForClassFields Flag and The declare Property Modifier - Build-Free Editing with Project References - Uncalled Function Checks - // @ts-nocheck in TypeScript Files - Semicolon Formatter Option