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

9298dcce5b2b0e88d8ffbb837192ca98?s=128

Sylvain Pontoreau

November 13, 2019
Tweet

Transcript

  1. 1.

    A TypeScript journey Microsoft Ignite The Tour - Paris 2019

    Sylvain Pontoreau Terance Moussoki Paul Souche Félix Billon
  2. 3.

    @ParisTypeScript Who we are and how to contact us @spontoreau

    @MoussokiT @lsagetlethias @felix_billon @paulsouche
  3. 6.

    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. 7.

    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. 8.

    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. 11.

    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. 12.

    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. 13.

    Decorators Currently experimental! Can be apply on: • Classes •

    Methods • Properties • Parameters TC 39: Draft "experimentalDecorators": true, "emitDecoratorMetadata": true,
  9. 14.

    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. 15.

    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. 16.
  12. 18.
  13. 19.
  14. 21.

    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
  15. 22.

    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
  16. 24.

    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
  17. 25.

    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)
  18. 26.

    Never / unknown / type alias / as const (3

    / 4) link Type alias is a “type variable” - Shorten long combinaison of union, intersection, mapped types
  19. 27.

    Never / unknown / type alias / as const (4

    / 4) link Cast as const returns a readonly literal type
  20. 28.

    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)
  21. 29.

    Literal / index types (2 / 2) link With index

    types the compiler checks code that use dynamic property names
  22. 30.

    Union / Intersection (1 / 2) link An union type

    is actually the “intersection” of its members
  23. 31.

    Union / Intersection (2 / 2) link An intersection type

    is actually the “union” of its members
  24. 32.

    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
  25. 33.

    Type Guards (2 / 3) link Most of the time

    we use it with a literal type
  26. 35.

    Mapped / Conditional types (1 / 6) link A mapped

    type is a “function type” that takes a type and map it thanks to indexable types
  27. 37.

    Mapped / Conditional types (3 / 6) link A conditional

    type selects one of two possible types based on a condition
  28. 42.

    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
  29. 43.

    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 :
  30. 44.

    --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
  31. 46.

    --strictNullChecks (3/4) - To handle null and undefined you can

    use : - Union type : link - Type Guard : link
  32. 47.

    --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.
  33. 48.

    --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
  34. 49.

    --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
  35. 50.

    --noImplicitThis (2/2) link - You can enforce the type of

    this by typings it as a first argument in a function
  36. 51.

    --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
  37. 52.

    --strictPropertyInitialisation (2/2) link - In some specific case you can

    use definite assignment assertion operator “!”
  38. 53.
  39. 54.

    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
  40. 55.

    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
  41. 56.

    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
  42. 57.

    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
  43. 58.

    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
  44. 59.

    - --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)
  45. 60.

    - --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)
  46. 61.

    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
  47. 66.

    - --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)
  48. 67.

    - --esModuleInterop is a flag to emit “__importStart” and “__importDefault”

    helpers (babel compatibility). it activates -- allowSyntheticDefaultImports esModuleInterop / allowSyntheticDefaultImports (1 / 2)
  49. 68.

    - --allowSyntheticDefaultImports is a flag to allow default imports even

    if declaration has no default export esModuleInterop / allowSyntheticDefaultImports (2 / 2)
  50. 70.

    What’s new in 3.7 : Null Coalescing link - Same

    as || but don’t treat NaN, 0 and empty string as falsy value.
  51. 71.

    What’s new in 3.7 : Optional Chaining link - Same

    as && but don’t treat NaN, 0 and empty string as falsy value.
  52. 73.

    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
  53. 74.
  54. 75.