Skip to content

Latest commit

 

History

History
1364 lines (981 loc) · 25.5 KB

slides.md

File metadata and controls

1364 lines (981 loc) · 25.5 KB
theme background title info class drawings transition mdc
default
/assets/bg.jpg
You might not need TypeScript
Notes for talk
text-center
persist
slide-left
true

You might not need TypeScript

Oliver Mckee


layout: image image: /assets/2023_most_wanted.png


layout: image image: /assets/2023_build_tool_libraries.png


layout: image image: /assets/1999.png


layout: image image: /assets/ecma.png


layout: image image: /assets/js20.png backgroundSize: 60rem


What did ES4 types look like?

```ts
// Interface
interface I {
  function f(): String;
}

// Class
class C implements I {
  function f() {
    return "foo";
  }
}

// Function
function add(a: int, b: int): int {
  return a + b;
}

// Union
type StringOrInt = (String,Int)
```

```ts
// Interface
interface I {
  f(): string;
}

// Class
class C implements I {
  f() {
    return "foo";
  }
}

// Function
function add(a: number, b: number): number {
  return a + b;
}

// Union
type StringOrNumber = string | number
```

Find out more at https://evertpot.com/ecmascript-4-the-missing-version


layout: image image: /assets/github.com_tc39_proposal-type-annotations.png


layout: image image: /assets/gogenerics.png backgroundSize: 60rem


layout: section

What can we do today?


layout: image image: /assets/jsdoc.png backgroundSize: 40rem


JSDoc relatives

JSDoc for JavaScript

/**
 * This is a simple JSDoc comment
 * @param {string} name - The name of the person
 * @returns {string} - The greeting
 */

Javadoc for Java

/**
 * This is a simple JavaDoc comment
 * @param {string} name - The name of the person
 * @returns {string} - The greeting
 */

PHPDoc for PHP

/**
 * This is a simple PHPDoc comment
 * @param string $name - The name of the person
 * @return string - The greeting
 */

layout: image image: /assets/typescript.svg backgroundSize: 20rem


layout: image image: /assets/typescript_jsdoc.png backgroundSize: 60rem


layout: image image: /assets/closurelibrary.png


layout: image image: /assets/typescript.svg backgroundSize: 20rem


layout: image image: /assets/importtag.png backgroundSize: 60rem


layout: image image: /assets/satisfies.png backgroundSize: 60rem


layout: section

JSDoc in action


Enabling JSDoc type checking

  1. Enable via comment
// @ts-check
  1. Enable via tsconfig.json
{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "noEmit": true,
  }
}
  1. Enable globally in VS Code
{
  "js/ts.implicitProjectConfig.checkJs": true,
}

transition: fade

Importing

```ts
// TypeScript

import type { MyObject } from "my-types"
```

```js
// JavaScript

/** @import { MyObject } from "my-types" */
```

transition: fade

Defining an Object

```ts
// TypeScript

/**
 * A user object
 */
interface User {
  /**
   * The name of the user
   */
  name: string;
  /**
   * The age of the user
   */
  age: number;
  /**
   * Whether the user has full access
   */
  fullAccess: boolean;
}

let myUser: User;
```

```js
// JavaScript

/**
 * A user object
 * 
 * @typedef {object} User
 * @property {string} name - The name of the user
 * @property {number} age - The age of the user
 * @property {boolean} fullAccess - Whether the user has full access
 */

/**
 * @type {User}
 */
let myUser;
```

transition: fade

Extending an Object

```ts
// TypeScript

interface Foo {
  /**
   * The A string
   */
  a: string;
}

interface Bar extends Foo {
  b: number;
}
```

```js
// JavaScript

/**
 * @typedef {object} Foo
 * @property {string} a - The A string
 */

/**
 * @typedef {object} Bar
 * @property {number} b - The B number
 */

/**
 * @typedef {Foo & Bar} FooBar
 */
```

transition: fade

Typing a variable

```ts
// TypeScript

const names: string[] = ["Alice", "Bob", "Eve"];
```

```js
// JavaScript

/**
 * @type {string[]}
 */
const names = ["Alice", "Bob", "Eve"];
```

transition: fade

Defining a constant

```ts
// TypeScript

const myObject = {
  foo: true,
  bar: false
} as const;
```

```js
// JavaScript

const myObject = /** @type {const} */ ({
  foo: true,
  bar: false
});
```

--- #19 transition: fade

Function

```ts
// TypeScript

/**
 * A function that adds two numbers
 *
 * @param a The first number
 * @param b The second number
 * @returns The sum of the two numbers
 */
export function add(a: number, b: number): number {
  return a + b;
}
```

```js
// JavaScript

/**
 * A function that adds two numbers
 *
 * @param {number} a The first number
 * @param {number} b The second number
 * @returns {number} The sum of the two numbers
 */
export function add(a, b) {
  return a + b;
}
```

transition: fade

Function Overloading

```ts
// TypeScript

function foo(a: string): void;
function foo(a: number): void;
function foo(a: string | number): void {}
```

```js
// JavaScript

/**
 * @overload
 * @param {string} a - The string value
 * @returns {string} string return value
 */

/**
 * @overload
 * @param {number} a - The number value
 * @returns {number} number return value
 */

/**
 * @param {string | number} a - The string or number value
 * @returns {string | number} string or number return value
 */
function foo(a) {
  return a;
}
```

transition: fade

Defining a callback

```ts
// TypeScript

/**
 * The function foo
 */
type Foo = (a: string, b: boolean) => void
```

```js
// JavaScript

/**
 * The function foo
 * 
 * @callback Foo
 * @param {string} a - The string value
 * @param {boolean} b - The boolean value
 * @returns {void} No return value
 */
```

transition: fade

Assigning this

```ts
// TypeScript

interface Foo {
  /**
   * The value
   */
  value: string;
  /**
   * The method
   */
  method(): void;
}

function bar(this: Foo) {
  this.method();
}
```

```js
// JavaScript

/**
 * @typedef {object} Foo
 * @property {string} value - The value
 * @property {() => void} method - The method
 */

/**
 * @this {Foo}
 */
function bar() {
  this.method();
}
```

transition: fade

Classes

```ts
class Foo {
  protected readonly a: string;

  private b: number;

  public constructor(a: string, b: number) {
    this.a = a;
    this.b = b;
  }
}
```

```js
class Foo {
  /**
   * The A string
   * @type {string}
   * @readonly
   * @protected
   */
  a;

  /**
   * The B number
   * @type {number}
   * @private
   */
  b;

  /**
   * The constructor
   * @param {string} a - The A string
   * @param {number} b - The B number
   */
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
}
```

transition: fade

Implements

```ts
// TypeScript

interface Bar {
  /**
   * The fuzz method
   */
  fuzz(): void;
}

class Foo implements Bar {
  fuzz() {}
}
```

```js
// JavaScript

/**
 * @typedef {object} Bar
 * @property {() => void} fuzz - The fuzz method
 */

/**
 * @implements {Bar}
 */
class Foo {
  fuzz() {}
}
```

transition: fade

Casting

```ts
// TypeScript

const mystery = undefined as unknown

const notMystery = mystery as string
```

```js
// JavaScript

/**
 * @type {unknown}
 */
const mystery = undefined

const notMystery = /** @type {string} */ (mystery)
```

transition: fade

Modifiers

```ts
// TypeScript

type Bar = {
  stringKey: string
  optionalNumber?: number
  optionalNumber2: number | undefined
  nullableString: string | null
  nullableOptionalString: string | null | undefined
  union: string | number
  nested: {
    stringKey: string
  }
}
```

```js
// JavaScript

/**
 * The bar object
 *
 * @typedef {object} Bar
 * @property {string} stringKey - The string key
 * @property {number=} optionalNumber - The optional number
 * @property {number} [optionalNumber2] - The optional number
 * @property {?string} nullableString - The nullable string
 * @property {?string=} nullableOptionalString - The nullable string
 * @property {string | number} union - The union type
 * @property {object} nested - The nested object
 * @property {string} nested.stringKey - The nested string key
 */
```

transition: fade

Type Guards

```ts
type LiteralString = "bar" | "foo"

function guard(value: LiteralString): value is LiteralString {
  return value === "foo" || value === "bar";
}

function asserts(value: LiteralString): asserts value is LiteralString {
  if (!guard(value)) {
    throw new Error("Invalid value");
  }
}
```

```js
/**
 * @typedef {"bar" | "foo"} LiteralString
 */

/**
 * 
 * @param {unknown} value 
 * @returns {value is LiteralString}
 */
function guard(value) {
  return value === "foo" || value === "bar";
}

/**
 * @param {unknown} value
 * @returns {asserts value is LiteralString} 
 */
function asserts(value) {
  if (!guard(value)) {
    throw new Error("Invalid value");
  }
}
```

transition: fade

Generics

```ts
// TypeScript

type Foo<T> = {
  /**
   * The value
   */
  value: T;
  /**
   * The promise
   */
  promise: Promise<T>;
}
```

```js
// JavaScript

/**
 * @template T
 * @typedef {object} Foo
 * @property {T} value - The value
 * @property {Promise<T>} promise - The promise
 */
```

transition: fade

Generic with base type and default

```ts
type Bar = {
  foo: string
};

type FooBar = {
  foo: string
  bar: string
}

type Foo<T extends Bar = FooBar> = {
  value: T
}
```

```js
/**
 * @typedef {object} Bar
 * @property {string} foo 
 */

/**
 * @typedef {object} FooBar
 * @property {string} foo
 * @property {string} bar
 */

/**
 * @template {Bar} [T = FooBar]
 * @typedef {object} Foo
 * @property {T} value - The value
 */
```

transition: fade

Comment Syntax

/**
 * Logs the amount to the console, throws a {@link RangeError} if the amount is less than 0
 * 
 * @param {number} amount - The amount to log
 * @returns {void}
 * @throws {RangeError} If the amount is less than 0, a {@link RangeError} is thrown
 */
function logAmount(amount) {
  if (amount > 0) {
    console.info(`The amount is ${amount}`);
  } else {
    throw new RangeError("amount cannot be less than 0");
  }
}

transition: fade

Comment Syntax

const STRING_CONSTANT = "Hello, World!";

/**
 * @typedef {object} Foo
 * @property {string} bar - [A string constant](#STRING_CONSTANT)
 * @property {string} baz - ![Fine](http://localhost:3030/assets/fine.webp)
 */

/**
 * @type {Foo}
 */
const foo = {};

foo.bar
foo.baz

layout: image image: /assets/babelguy.png transition: fade backgroundSize: 60rem


layout: section

What's next for JSDoc?


transition: fade

Coming soon to a JSDoc near you

New JSDocs tags

@nonnull

```ts
// TypeScript

let items = [1, 2, 3, 4, 5];

let item = items.pop()!;
```

```js
// JavaScript

let items = [1, 2, 3, 4, 5];

let item = /** @nonnull */ (items.pop());
```

Coming soon to a JSDoc near you

New JSDocs tags

@specialize

```ts
// TypeScript

const [optionalString, setOptionalString] = useState<string | null>(null);
```

```js
// JavaScript

/**
 * @specialize {string | null}
 */
const [optionalString, setOptionalString] = useState(null);
```

layout: image image: /assets/jsdocscheatsheet.png transition: fade backgroundSize: 50rem


transition: fade

All of this to avoid...


layout: image image: /assets/tsnode.png transition: fade backgroundSize: 40rem

All of this to avoid...


All of this to avoid...

                                      }
                                    }
                                  }
                                }
                              }
                            // When I wrote this, only God and I understood what I was doing
                            // Now, God only knows
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      } catch {
        return null;
      }
    }
  }
}

https://github.com/MrBazlow/youmightnotneedtypescript <style> .qr-code { position: absolute; background-color: white; height: 300px; width: 300px; bottom: 1rem; right: 2rem; clip-path: inset(30px 30px 30px 30px round 20px); } .slide-link { position: absolute; bottom: 0.75rem; right: 3.75rem; } </style>