# Syntax
⚡️ Tags:
📍Typescript
# Types
# Enum
const enum Suit {
Clubs,
Diamonds,
Hearts,
Spades
}
var d = Suit.Diamonds;
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
# Union type
type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
function rollDice(): 1 | 2 | 3 | 4 | 5 | 6 {
return (Math.floor(Math.random() * 6) + 1) as 1 | 2 | 3 | 4 | 5 | 6;
}
const result = rollDice();
# Intersection type
type LinkedList<T> = T & { next: LinkedList<T> };
interface Person {
name: string;
}
var people: LinkedList<Person>;
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
interface A {
a: string;
c: string;
}
interface B {
b: string;
c: number
}
type AB = A & B // { a: string; b: string: c: number };
type BA = B & A // { a: string; b: string: c: string };
# Tuple type
var x: [string, number];
x = ["hello", 10];
# never
type
The never
type has the following characteristics:
never
is a subtype of and assignable to every type.- No type is a subtype of or assignable to
never
(exceptnever
itself). - In a function expression or arrow function with no return type annotation, if the function has no
return
statements, or onlyreturn
statements with expressions of type never, and if the end point of the function is not reachable (as determined by control flow analysis), the inferred return type for the function is never. - In a function with an explicit
never
return type annotation, allreturn
statements (if any) must have expressions of typenever
and the end point of the function must not be reachable.
Use case: Declare a function that throws an Error in TypeScript (opens new window)
function sometimesThrow(): number | never {
if (Math.random() > 0.5) {
return 100;
}
throw new Error('Something went wrong');
}
// 👇️ const result: number
const result = sometimesThrow();
console.log(result.toFixed());
WARNING
You can't specify the type of error a function throws
# void
we can only assign undefined or null to them.
let unusable: void = undefined;
let tempNum: void = undefined;
function helloUser(): void {
alert("This is a welcome message");
}
# Generics
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
# namespace vs. module
- “Internal modules” are closer to what most people would call a
namespace
- “External modules” in JS speak really just are
modules
now.
// BEFORE
module Math {
export function add(x, y) { ... }
}
// AFTER
namespace Math {
export function add(x, y) { ... }
}
# Assertion
# Assert Function
function multiply(x, y) {
assert(typeof x === "number");
assert(typeof y === "number");
return x * y;
}
# const assertions
let foo = {
name: "foo",
contents: arr
} as const;
foo.name = "bar"; // error!
foo.contents = []; // error!
foo.contents.push(5); // ...works!
# Type parameters as constraints
function assign<T extends U, U>(target: T, source: U): T {
for (let id in source) {
target[id] = source[id];
}
return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
assign(x, { b: 10, d: 20 });
assign(x, { e: 0 }); // Error
# Type guards
interface UserAccount {
id: number;
email?: string;
}
// access
user!.email!.length;
# Others
# Optional Chaining
let x = foo?.bar.baz();
// explain:
// let x = foo === null || foo === undefined ? undefined : foo.bar.baz();
if (foo && foo.bar && foo.bar.baz) {
// ...
}
// After-ish
if (foo?.bar?.baz) {
// ...
}
# Dynamic import
async function getZipFile(name: string, files: File[]): Promise<File> {
const zipUtil = await import("./utils/create-zip-file");
const zipContents = await zipUtil.getContentAsBlob(files);
return new File(zipContents, name);
}
# Computed properties
Recursive as well
type NeighborMap = { [name: string]: Node };
type Node = { name: string; neighbors: NeighborMap };
function makeNode(name: string, initialNeighbor: Node): Node {
return {
name: name,
neighbors: {
[initialNeighbor.name]: initialNeighbor,
},
};
}
# Class
# Readonly properties
interface Point {
readonly x: number;
readonly y: number;
}
class Foo {
readonly a = 1;
readonly b: string;
constructor() {
this.b = "hello"; // Assignment permitted in constructor
}
}
# Decorators
function classDecorator<T extends { new (...args: any[]): {} }>(
constructor: T
) {
return class extends constructor {
newProperty = "new property";
hello = "override";
};
}
@classDecorator
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
class C {
@readonly
@enumerable(false)
method() { ... }
}
function readonly(target, key, descriptor) {
descriptor.writable = false;
}
function enumerable(value) {
return function (target, key, descriptor) {
descriptor.enumerable = value;
};
}
# with Json
interface MyObj {
myString: string;
myNumber: number;
}
let obj: MyObj = JSON.parse('{ "myString": "string", "myNumber": 4 }');
← NodeJs tools Types →