<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>reveal.js</title> <link rel="stylesheet" href="https:https://unpkg.com/reveal.js/css/reset.css"> <link rel="stylesheet" href="https://unpkg.com/reveal.js/css/reveal.css"> <link rel="stylesheet" href="https://unpkg.com/reveal.js/css/theme/black.css"> <!-- Theme used for syntax highlighting of code --> <link rel="stylesheet" href="https://unpkg.com/reveal.js/lib/css/monokai.css"> <style> .reveal pre code { max-height: unset; padding: .5rem; border-radius: .25rem; } </style> <!-- Printing and PDF exports --> <script> var link = document.createElement('link'); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = window.location.search.match(/print-pdf/gi) ? 'https://unpkg.com/reveal.js/css/print/pdf.css' : 'https://unpkg.com/reveal.js/css/print/paper.css'; document.getElementsByTagName('head')[0].appendChild(link); </script> </head> <body> <div class="reveal"> <div class="slides"> <section data-background-color="#357EDD"> <h1>Typescript</h1> <ul class="fragment"> <li>What is typescript?</li> <li>History & Today</li> <li>Why?</li> <li>Basics</li> <li>Typescript Utilities</li> <li>Examples</li> <li>Future</li> </ul> </section> <section> <section data-markdown data-background-color="#CDECFF"> <script type="text/template"> ## What is Typescript? - Superset of Javascript <!-- .element: class="fragment" --> - Enables typschecking <!-- .element: class="fragment" --> </script> </section> <section data-transition="fade-out slide-in"> <h3>Javascript</h3> <pre><code data-trim class="hljs"> let a = 'a string' a = 5 a = [1, 'two', {three: true}] </code></pre> </section> <section data-transition="fade-in slide-out"> <h3>Typescript</h3> <pre><code data-trim class="hljs"> let a = 'a string' // a is a string now a = 5 // ❌ a = [1, 'two', {three: true}] // ❌ </code></pre> </section> </section> <section data-background-color="#FBF1A9"> <section data-markdown> <script type="text/template"> ## Brief History Lesson - <!-- .element: class="fragment" --> Development started in 2009 (codename Strada) - <!-- .element: class="fragment" --> Problems scaling the office 365 suite (released June 2011) - <!-- .element: class="fragment" --> Lead by Anders Hejlsberg (Author of C#, Delphi & Tubro Pascal) and Luke Hoban (Part of tc39) - <!-- .element: class="fragment" --> 2012: <span><!-- .element: class="fragment fade-in" --><span><!-- .element: class="fragment highlight-red" -->World End</span></span><span> <!-- .element: class="fragment fade-in" -->; Released to public `v0.8`</span> - <!-- .element: class="fragment" --> 2014: Moved to Github </script> </section> <section data-markdown> <script type="text/template"> ## Today <small>2 Oct. 2019</small> - <!-- .element: class="fragment" --> ~54k Stargazers - <!-- .element: class="fragment" --> ~10k closed PRs (167 open) - <!-- .element: class="fragment" --> ~20k closed issues (~3.5k open) - <!-- .element: class="fragment" --> 419 Contributors - <!-- .element: class="fragment" --> Made & <b>Maintained</b> by Microsoft </script> </section> </section> <section data-background-color="#FFDFDF"> <section data-markdown> <script type="text/template"> ## So Why? - <!-- .element: class="fragment" --> Less Errors - <!-- .element: class="fragment" --> Less Bug-Hunting - <!-- .element: class="fragment" --> More work gets done - <!-- .element: class="fragment" --> Maintainability - <!-- .element: class="fragment" --> Enables fast fixes - <!-- .element: class="fragment" --> Dev. must not be context aware - <!-- .element: class="fragment" --> Autocompletition, "Smart" IDEs, etc. </script> </section> <section data-background-image="https://media.giphy.com/media/YXpp9YxWhyWBy/giphy.gif"></section> </section> <section data-background-color="#E8FDF5"> <section> <h2>TS Config</h2> <pre class="fragment"><code data-trim class="hljs"> npm i typescript tsc --init </code></pre> </section> <section> <h3>General</h3> <ul> <li class="fragment">target <small>(ES2014, ..., ES2019, ESNEXT, ...)</small></li> <li class="fragment">module <small>(commonjs, es2016, esnext, ...)</small></li> <li class="fragment">jsx</li> <li class="fragment">esModuleInterop</li> <li class="fragment">allowSyntheticDefaultImports</li> <li class="fragment">experimentalDecorators</li> <li class="fragment">emitDecoratorMetadata</li> </ul> </section> <section> <h3>Type Cheking</h3> <ul> <li class="fragment">noImplicitAny</li> <li class="fragment">strictNullChecks</li> <li class="fragment">strictFunctionTypes</li> <li class="fragment">strictBindCallApply</li> <li class="fragment">strictPropertyInitialization</li> <li class="fragment">noImplicitThis</li> <li class="fragment">alwaysStrict</li> <li class="fragment">noImplicitReturns</li> <li class="fragment">noFallthroughCasesInSwitch</li> </ul> </section> <section> <h3>Production</h3> <ul> <li class="fragment">noUnusedLocals</li> <li class="fragment">noUnusedParameters</li> <li class="fragment">removeComments</li> </ul> </section> </section> <section> <section> <h2>Basics</h2> </section> <section data-transition="slide-id fade-out"> <h3>Simple types</h3> <pre class="fragment"><code data-trim class="hljs"> const a: string = 'a string' const b: number = 5 const c: boolean = true const d: string[] = ['a', 'b', 'c'] const e: number[] = [1, 2, 3] </code></pre> </section> <section data-transition="fate-in slide-out"> <h3>Simple types</h3> <pre><code data-trim class="hljs"> const a = 'a string' const b = 5 const c = true const d = ['a', 'b', 'c'] const e = [1, 2, 3] </code></pre> </section> <section> <h3>Types</h3> <pre class="fragment"><code data-trim class="hljs"> type StrinOrNumber = string | number </code></pre> <pre class="fragment"><code data-trim class="hljs"> type StringOrNumberOrBoolean = StringOrNumber | boolean </code></pre> </section> <section> <h3>Modifiers</h3> <pre class="fragment"><code data-trim class="hljs"> const a?: string // string | undefined const obj = { a: string, b?: number, } funntion log(msg?: string) {} </code></pre> <pre class="fragment"><code data-trim class="hljs"> class { b!: string } obj!.one!.two!.three </code></pre> </section> <section data-transition="slide-id fade-out"> <h3>Interfaces</h3> <pre class="fragment"><code data-trim class="hljs"> interface Pizza { slices: number round: boolean name: string } const pizza: Pizza = { slices: 4, round: true, name: 'Hawaii' } </code></pre> </section> <section data-transition="slide-out fade-in"> <h3>Interfaces</h3> <pre><code data-trim class="hljs"> interface Pizza { slices: 4 | 8 round: boolean name: 'Margherita' | 'Parmigiana' } const pizza: Pizza = { slices: -1, // ❌ round: true, name: 'Margherita' } </code></pre> </section> <section> <h3>Interfaces</h3> <pre><code data-trim class="hljs"> interface A { one: string } interface B extends A { two: number three?: string } </code></pre> </section> <section> <h3>Interfaces</h3> <pre><code data-trim class="hljs"> interface Project { name: string, paymentBasis: 'fix' | 'hour' } </code></pre> <pre class="fragment"><code data-trim class="hljs"> interface GoodProject extends Project { paymentBasis: 'hour' } </code></pre> </section> <section> <h3>Functions</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> function add(x: number, y: number): number { return x + y } const add = (x: number, y: number): number => { return x + y } </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> function choose<T, P>(a: T, b: P): T | P { if (something) return a else return b } </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> const waitForMe = async (text:string): Promise<string> => text </code></pre> </section> <section> <h3>Overloading</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> function add(x: number): number function add(x: number, y: number = 1): number { return x + y } </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> function add(a: string, b: string): string function add(a: number, b: number): number function add(a: string | number, b: string | number): string | number { if (a.constructor.name === 'String') return a + b else return a + b } </code></pre> </section> <section> <h3>Classes</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> class User { private id: string public readonly username: string friends: User[] = [] constructor() { this.id = 'abc' this.username = 'John Doe' } private doSomeStuff() {} } </code></pre> </section> <section> <h3>Generics</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> function choose<T, P>(a: T, b: P): T | P { if (something) return a else return b } </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> type Something<T> = { a: string, b: T } </code></pre> </section> </section> <section> <section> <h2>Typescript Utilities Types</h2> <ul class="fragment"> <li>Partial & Required</li> <li>Readonly</li> <li>Pick & Omit</li> </ul> </section> <section> <h3>Partial / Required</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> interface Props { a: number; b: string; }; const x: Props = { a: 5 }; // Error: property 'b' missing const y: Partial<Props> = { a: 5 }; // OK </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> interface Props { a?: number; b?: string; }; const x: Props = { a: 5 }; // OK const y: Required<Props> = { a: 5 }; // Error: property 'b' missing </code></pre> </section> <section> <h3>Readonly</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> interface Todo { title: string; } const todo: Readonly<Todo> = { title: 'Delete inactive users', }; todo.title = 'Hello'; // Error: cannot reassign a readonly property </code></pre> </section> <section> <h3>Pick / Omit</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> interface Todo { title: string; description: string; completed: boolean; } const todo: Pick<Todo, 'title' | 'completed'> = { title: 'Clean room', completed: false, }; </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> interface Todo { title: string; description: string; completed: boolean; } const todo: Omit<Todo, 'description'> = { title: 'Clean room', completed: false, }; </code></pre> </section> <section> <h2>Also there are...</h2> <ul> <li>Exclude & Extract</li> <li>Record</li> <li>NonNullable</li> <li>ReturnType</li> <li>InstanceType</li> <li>ThisType</li> </ul> </section> </section> <section> <section> <h2>Examples</h2> </section> <section> <h3>Constructor</h3> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> class Auto { wheels: number constructor(wheel: number) { this.wheels = wheel } } </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> class Auto { constructor(private wheel: number) { } } </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> class Auto { wheels!: number constructor(init: typeof Auto) { Object.assign(this, init) } } </code></pre> </section> <section> <h3>Advanced Stuff</h3> <pre><code data-trim class="hljs"> class Auto { wheels?: number doors?: number // ... constructor(init: Partial<Auto>) { Object.assign(this, init) } } const a = new Auto({ doors: 5, }) </code></pre> </section> <section> <h3>Advanced Stuff</h3> <pre><code data-trim class="hljs"> type RequireSome<T, K extends keyof T> = { [X in Exclude<keyof T, K>]?: T[X] } & { [P in K]-?: T[P] } class Auto { wheels!: number doors?: number // ... constructor(init: RequireSome<Auto, 'wheels'>) { Object.assign(this, init) } } const a = new Auto({ wheels: 4, doors: 5, }) </code></pre> </section> <section> <h3>React Higher Order Components</h3> <pre><code data-trim class="hljs" data-line-numbers="1,2,5"> function withLayout<P extends object>(WrappedComponent: React.ComponentType<P>) { return (props: P) => ( <div id='app'> <Header/> <WrappedComponent {...props}/> <Footer/> </div> ); } </code></pre> </section> </section> <section> <section> <h2>Future</h2> </section> <section> <h3>Optional Chaining</h3> <i>TS 3.7</i> <pre class="fragment"><code data-trim class="hljs"> a && a.b && a.b.c // 🤬 </code></pre> <pre class="fragment"><code data-trim class="hljs"> a?.b?.c // 🚀 </code></pre> </section> <section> <h3>Null Coalescing</h3> <i>TS 3.7</i> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> something || 'default' </code></pre> <pre class="fragment fade-in-then-semi-out"><code data-trim class="hljs"> false || 'default' // => 'default' 0 || 'default' // => 'default' </code></pre> <pre class="fragment"><code data-trim class="hljs"> something ?? 'default' // 🚀 </code></pre> <pre class="fragment"><code data-trim class="hljs"> 0 ?? 'default' // => 0 false ?? 'default' // => false </code></pre> <pre class="fragment"><code data-trim class="hljs"> (something === null || something === undefined) ? something : 'default' </code></pre> </section> </section> </div> </div> <script src="https://unpkg.com/reveal.js/js/reveal.js"></script> <script> Reveal.initialize({ width: "100%", height: "100%", margin: .1, minScale: 1, maxScale: 1, transition: 'slide', hash: true, fragmentInURL: true, slideNumber: 'c/t', dependencies: [{ src: 'https://unpkg.com/reveal.js/plugin/markdown/marked.js' }, { src: 'https://unpkg.com/reveal.js/plugin/markdown/markdown.js' }, { src: 'https://unpkg.com/reveal.js/plugin/notes/notes.js', async: true }, { src: 'https://unpkg.com/reveal.js/plugin/highlight/highlight.js', async: true } ] }); </script> </body> </html>