{Typescript}

 Supercharging Your JavaScript Development

{Hello!}

Javascript is free!

function countCharacter(value){
  return value.length
}

var name = "Danger"
countCharacter(name) // 5 

var name = 1 
countCharacter(name) // ? 

var name = false 
countCharacter(name) // ? 


// Previously: sayMyName(firstName, lastName) { ...
function sayMyName(fullName) {
	console.log(`You acting kind of shady, ain't callin' me ${fullName}`);
}
sayMyName("Beyoncé", "Knowles");
# var.camp 2.0 
if(typeof name !== string) throw "Name should be string";

// find the error in this code 
const obj = { width: 10, height: 15 };
const area = obj.width * obj.heigth;
# VAR.CAMP 2.0

Ever written something like this?

<div>
  {
  	data.products.map(item=><Card data={item}/>); // 😵 Cannot read the property map of undefined .. or blah blah
  }
</div>
// javascript has loose documentation
// what is the type of a and b
function add(a, b) {
  return a + b
}

const inputA = input()("Some async input for a!") // inputA could be anything
const inputB = input()("Some async input for b!") // inputB could be anything
add(inputA, inputB)
# VAR.CAMP 2.0

TS provides documentation

Move potential errors from runtime to compile time

function add(a: number, b: number): number {
  return a + b
}
add(3, "4")
// 😵 Argument of type 'string' is not assignable to parameter of type 'number'.

Of course we can have something like JS Docs

/**
* Add two numbers
* @param {number} a
* @param {number} b
* @returns {number} total value
*/
function sum(a, b) { /* ... */ }
  • Nothing stops JSDoc descriptions from being wrong about code.
  • Even if your JSDoc descriptions were previously correct, during code refactors it can be difficult to find all the now-invalid JSDoc comments related to your changes.
  • Describing complex objects is unwieldy and verbose.
# VAR.CAMP 2.0
# VAR.CAMP 2.0
interface Address {
  street: string;
  city: string;
  state: string;
  zipCode: string;
}

interface User {
  name: string;
  email: string;
  password: string;
  address: Address;
}

function createUser(name: string, email: string, password: string, address: Address): User {
  return {
    name,
    email,
    password,
    address : address
  };
}

const address = {
  street: "123 Main St",
  city: "Anytown",
  state: "CA",
  zipCode: "12345",
};

const newUser = createUser("John Doe", "john@example.com", "secret", address);

Great documentation 

# VAR.CAMP 2.0

Stronger developer tooling

{Typescript}

Let's talk about Typescript !

Start with zero

# VAR.CAMP 2.0
# VAR.CAMP 2.0
# VAR.CAMP 2.0

Types are opt-in

Created By Microsoft in early 2010 and open-sourced in 2012.

Typescript has four things

  • Programming language
  • Type checker
  • Compiler
  • Language server
# VAR.CAMP 2.0
# VAR.CAMP 2.0

Notations!

😵  Error

🤯  Tips

😍  Great

# VAR.CAMP 2.0
# VAR.CAMP 2.0
function sayMyName(fullName) {
  console.log(`Hello ${fullName}`);
}
sayMyName("Beyoncé", "Knowles"); // 😵 Expected 1 argument, but got 2.
const firstName = "Georgia";
const nameLength = firstName.length(); // 😵 This expression is not callable.

# VAR.CAMP 2.0

Some of the basic primitives in Typescript

  • number
  • string
  • boolean
  • undefined
  • null
let someNumber = 10;
let someString = "Hello String";
let isLive = true;
let someUndefined;

let somePossibleNull = Math.random() > 0.5 ? null : 10;
someNumber.toFixed(0.2)
someString.length // 11
somePossibleNull.toFixed() // 😵 possibly null

Some of the basic primitives in Typescript

  • number
  • string
  • boolean
  • undefined
  • null
# VAR.CAMP 2.0

Type system

Set of rules for a language to understand what types in a program contract may have.

Simply Typescript system works by

• Reading in your code and understanding all the types and values in existence
• For each value, seeing what type its initial declaration indicates it may contain
• For each value, seeing all the ways it’s used later on in the code
• Complaining to the user if a value’s usage doesn’t match its type

# VAR.CAMP 2.0

Type of errors

Syntax error : Blocking Typescript from being converted to Javascript

let let wat;
//
~~~
// Error: ',' expected.

Type error : Something mismatched has been detected by the type checker

let eventName : string = "Var.Camp 2.0";
eventName = "Var.Camp 2.0";

eventName = 20; 		 // 😵 Type 'number' is not assignable to type 'string'.
eventName.toSomething(); // 😵 Type 'number' is not assignable to type 'string'. 
type possiblyNumberOrString = number | string;

let value : possiblyNumberOrString = Math.random() > 0.5 ? 12 : "Twelve";

let physicist = Math.random() > 0.5 ? "Marie Curie" : 84;

physicist.toString(); // Ok vaild for both type

physicist.toUpperCase(); // 😵 Error: Property 'toUpperCase' does not exist on type 'string | number'.

physicist.toFixed(); // 😵 Property 'toUpperCase' does not exist on type 'number'.
# VAR.CAMP 2.0

Union Types

// Type of scientist: number | string
let scientist = Math.random() > 0.5 ? "Rosalind Franklin" : 51;

scientist.toUpperCase(); // 😵 Property 'toUpperCase' does not exist on type 'string | number'.

if (scientist === "Rosalind Franklin") {
	scientist.toUpperCase(); // Ok
} 

if (typeof scientist === "string") {
	scientist.toUpperCase(); // Ok 
}

typeof scientist === "string" ? scientist.toUpperCase() // Ok: string
				: scientist.toFixed(); // Ok: number
# VAR.CAMP 2.0

Narrowing

const poet = {
    born: 1935,
    name: "Mary Oliver",
};
poet['born']; // Type: number
poet.name; // Type: string
poet.end; // 😵 Error: Property 'end' does not exist on type '{ born: number; name: string; }'.

type Poet = {
  born: number;
  name: string;
};
let poetLater: Poet;
// Ok
poetLater = {
  born: 1935,
  name: "Sara Teasdale",
};
poetLater = "Emily Dickinson"; //😵 Error: Type 'string' is not assignable to 'Poet'.
# VAR.CAMP 2.0

Object types

type WithFirstName = {
	firstName: string;
};
type WithLastName = {
	lastName: string;
};
const hasBoth = {
	firstName: "Lucille",
	lastName: "Clifton",
};

let withFirstName: WithFirstName = hasBoth; // Ok: `hasBoth` contains a `firstName` property of type `string`

let withLastName: WithLastName = hasBoth; // Ok: `hasBoth` contains a `lastName` property of type `string`
# VAR.CAMP 2.0

Structural typing

type FirstAndLastNames = {
    first: string;
    last: string;
};

// Ok
const hasBoth: FirstAndLastNames = {
    first: "Sarojini",
    last: "Naidu",
};
const hasOnlyOne: FirstAndLastNames = {
    first: "Sappho"
};
// 😵 Property 'last' is missing in type '{ first: string; }'
// 😵 but required in type 'FirstAndLastNames'.

const extraProperty: FirstAndLastNames = {
  	first: "Sarojini",
  	last: "Naidu",
  	age : 10
};
// 😵 'age' does not exist in type 'FirstAndLastNames'.
# VAR.CAMP 2.0

Using Checking

type Book = {
  author?: string; // optional author
  pages: number;
};

// Ok
const ok: Book = {
  author: "Rita Dove",
  pages: 80,
};

const missing: Book = {
  author: "Rita Dove",
};
// 😵 Error: Property 'pages' is missing in type
// '{ author: string; }' but required in type 'Book'.
# VAR.CAMP 2.0

Optional properties

const poem = Math.random() > 0.5
  ? { name: "The Double Image", pages: 7 }
  : { name: "Her Kind", rhymes: true };
/**
 * {
 *      name : string;
 *      pages : number;
 * }
 * |
 * {
 *      name : string;
 *      rythmes : boolean
 * }
 * 
 */
poem.name;      // string
poem.pages;     // number | undefined
poem.rhymes;    // booleans | undefined
# VAR.CAMP 2.0

Inferred object union types

type Poet = {
  born: number;
  name: string;
};

interface Poet {
  born: number;
  name: string;
}

let valueLater: Poet;
// Ok
valueLater = {
  born: 1935,
  name: 'Sara Teasdale',
};

valueLater = "Emily Dickinson";	// 😵 Error: Type 'string' is not assignable to 'Poet'.

// 😵 Error: Type 'boolean' is not assignable to type 'number'.
valueLater = {
  born: true,
  name: 'Sappho'
};
# VAR.CAMP 2.0

Interfaces

interface Animal {
  name: string;
  sound: string;
  readonly legs: number;
  run(speed: number): void;
}

interface Cat extends Animal {
  meow(): void;
}

// OK !
const myCat: Cat = {
  name: "Fluffy",
  sound: "meow",
  legs: 4,
  run(speed: number) {
    console.log(`I'm running at ${speed} mph!`);
  },
  meow() {
    console.log("Meow!");
  },
};
# VAR.CAMP 2.0

Some differences

{ More }

// any 
let anyValue: any;
anyValue = "Lucille Ball"; // Ok
anyValue = 123; // Ok
console.log(anyValue); // Ok

// unknown
function greetComedian(name: unknown) {
	console.log(`Announcing ${name.toUpperCase()}!`); // 😵 Error: Object is of type 'unknown'.
}

// using narrowing
function greetComedianSafety(name: unknown) {
    if (typeof name === "string") {
        console.log(`Announcing ${name.toUpperCase()}!`); // Ok
    } else {
        console.log("Well, I'm off.");
    }
}
greetComedianSafety("Var.Camp"); // "Announcing VAR.CAMP!" 
greetComedianSafety({}); //  "Well, I'm off." 
# VAR.CAMP 2.0

Top types

function isNumberOrString(value: unknown) {
    return ['number', 'string'].includes(typeof value);
}

function logValueIfExists(value: number | string | null | undefined) {
  if (isNumberOrString(value)) {
      // 😳 ? Type of value: number | string
      // 😵 'value' is possibly 'null' or 'undefined'
      console.log(value.toString());
  } else {
      // Type of value: null | undefined
      console.log("value does not exist:", value);
  }
}



# VAR.CAMP 2.0

Type predicates

function typePredicate(input: WideType): input is NarrowType;

function isNumberOrString(value: unknown) : value is number | string {
    return ['number', 'string'].includes(typeof value);
}

function logValueIfExists(value: number | string | null | undefined)  {
  if (isNumberOrString(value)) {
      // 😍 Type of value: number | string
      console.log(value.toString());
  } else {
      // Type of value: null | undefined
      console.log("value does not exist:", value);
  }
}

logValueIfExists(null)
# VAR.CAMP 2.0

Type predicates

interface Box<T> {
	inside: T;
}
let stringyBox: Box<string> = {
	inside: "abc",
};
let numberBox: Box<number> = {
	inside: 123,
}
let incorrectBox: Box<number> = {
	inside: false,
	// 😵 Error: Type 'boolean' is not assignable to type 'number'.
}

function makeTuple<First, Second>(first: First, second: Second) {
	return [first, second] as const;
}
makeTuple(true, "abc"); // OK Type of value: readonly [boolean, string]

makeTuple<string, number>("abc", 123); // OK ! Type: { key: string; value: number }

makeTuple<"abc", 123>("abc", 123); // Type: { key: "abc"; value: 123 }

makePair<string>("abc", 123); // 😵 Error: Expected 2 type arguments, but got 1.
# VAR.CAMP 2.0

Generics

// Type: Promise<unknown>
const resolvesUnknown = new Promise((resolve) => {
	setTimeout(() => resolve("Done!"), 1000);
});

// Type: Promise<string>
const resolvesString = new Promise<string>((resolve) => {
	setTimeout(() => resolve("Done!"), 1000);
});

// // Type: (text: string) => Promise<number>
async function lengthAfterSecond(text: string) {
	new Promise((resolve) => setTimeout(resolve, 1000))
	return text.length;
}

async function getData<T>(): Promise<T> {
    const [data,setData] = useState<T>()
    useEffect(()=>{
        //  set data
	},[])
    return data 
}
interface Data {
    name : string;
    email : string;
}
const res  = getData<Data>();
# VAR.CAMP 2.0

Generics & Async

# VAR.CAMP 2.0

Declaration files

// modules.d.ts
declare module "my-example-lib" {
	export const value: string;
}

// index.ts
import { value } from "my-example-lib";
console.log(value); // Ok

// styles.d.ts
declare module "*.module.css" {
	const styles: { [i: string]: string };
	export default styles;
}

// component.ts
import styles from "./styles.module.css";
styles.anyClassName; // Type: string
# VAR.CAMP 2.0

Example

// styles.d.ts
declare module "*.module.css" {
	const styles: { [i: string]: string };
	export default styles;
}

// component.ts
import styles from "./styles.module.css";
styles.anyClassName; // Type: string


// globals.d.ts
declare const version: string;
// version.ts
export function logVersion() {
	console.log(`Version: ${version}`); // Ok
}

{ Definately Typed }

Definitely typed is

  • a giant community repo
  • high-quality type definitions for popular  libraries and modules
  • Can install via npm and used in  projects
  • Make life easier for devs when dealing with libraries or modules
# VAR.CAMP 2.0
{
	"dependencies": {
		"react": "^18.1.0"
	},
	"devDependencies": {
		"@types/react": "^18.0.9"
	},
}

{ USING IDE Features }

# VAR.CAMP 2.0
# VAR.CAMP 2.0
# VAR.CAMP 2.0

{ Thanks }

Made with Slides.com