Skip to content

Instantly share code, notes, and snippets.

@a7madgamal
Last active May 18, 2022 21:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save a7madgamal/11c4ec4fbb8a36b16ed2f269c34676ab to your computer and use it in GitHub Desktop.
Save a7madgamal/11c4ec4fbb8a36b16ed2f269c34676ab to your computer and use it in GitHub Desktop.
Typescript intro
////////////////////////////////////////////////////////////////////////////////
// Booleans
////////////////////////////////////////////////////////////////////////////////
const trueOrFalse: boolean = true;
// trueOrFalse = 3
// TS is smart, no need to type EVERYTHING!
const alsoTrueOrFalse = true;
// alsoTrueOrFalse = 3
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Numbers
////////////////////////////////////////////////////////////////////////////////
const num: number = 4;
// tip: you can use _ as visual separator like 100_000_000
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Strings
////////////////////////////////////////////////////////////////////////////////
const str = 'My type is an exact value because of const';
let str2 = 'My type is string because of let';
// as const can change that is needed
let str3 = 'My type is string because of let' as const;
// and TS will make sure we can't change it later ;)
// str3 = "nope";
let specific: 'exact_value';
// works
specific = 'exact_value';
// anything else wont work
// specific = 'test';
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// null and undefined
////////////////////////////////////////////////////////////////////////////////
// since TS can't tell which type of value will come it sets type of any
const noIdea = undefined;
let mustBeEmpty: void = undefined;
// mustBeEmpty = true;
// depends on strictiness settings
// mustBeEmpty = null;
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Arrays
////////////////////////////////////////////////////////////////////////////////
const arrayOfStrings: string[] = ['hi', 'there'];
// same
const alsoArrayOfStrings: Array<string> = ['hi', 'there'];
// can read but can't push!
const readOnlyArrayOfStrings: ReadonlyArray<string> = ['only', 'us'];
// readOnlyArrayOfStrings.push('me too?')
let dimentionsTuple: [number, number];
dimentionsTuple = [12, 5];
// dimentionsTuple = [12, 5, 12];
const dimentionsTuplesArray: [number, number][] = [
[12, 5],
[23, 23],
[10, 34],
];
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Extract array elemnts type
////////////////////////////////////////////////////////////////////////////////
const persons = [
{ name: 'Alice', age: 15 },
{ name: 'Bob', age: 23 },
{ name: 'Eve', age: 38 },
];
type PersonType = typeof persons[number];
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// 💣 any
////////////////////////////////////////////////////////////////////////////////
const anything: any = JSON.parse('{}');
anything();
anything.crazy.danger.errors();
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// ⚠️ unknown
////////////////////////////////////////////////////////////////////////////////
const saferObject: unknown = JSON.parse('{}');
// saferObject.lessErrors;
// saferObject();
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// ⚠️ as keyword
////////////////////////////////////////////////////////////////////////////////
const wrong = 1 as any;
const wrong1 = 1 as unknown;
// const wrong2 = true as number;
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Objects
////////////////////////////////////////////////////////////////////////////////
let userObj: {
name: string;
age: number;
isAdmin: boolean;
anotherObject: { parentIds: number[] };
};
userObj = {
name: 'Mido',
age: 30,
isAdmin: true,
anotherObject: {
parentIds: [1, 2, 3],
},
};
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// separate types
////////////////////////////////////////////////////////////////////////////////
type JustType = {
someString: string;
};
const obj: JustType = {
someString: 'something',
};
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// nesting types
////////////////////////////////////////////////////////////////////////////////
type NestedType = {
someString: string;
};
type UserType = {
name: string;
age: number;
isAdmin: boolean;
anotherObject: NestedType;
};
const User: UserType = {
name: 'Mido',
age: 30,
isAdmin: true,
anotherObject: {
someString: 'something',
},
};
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// optional types
////////////////////////////////////////////////////////////////////////////////
type AnotherUserType = {
name: string;
// means number OR undefined (OR null, if not strict mode)
age?: number;
};
// can be skipped
const AnotherUser: AnotherUserType = {
name: 'Mido',
};
const EvenAnotherUser: AnotherUserType = {
name: 'Mido',
// but if provided, it must match
// age: true,
};
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// functions
////////////////////////////////////////////////////////////////////////////////
function nothing(): void {}
function fn(arg1: string) {
return arg1.length > 3;
}
function fn2(arg1: string): boolean {
return arg1.length > 3;
}
function fn3(arg1: string, arg2?: number): string {
if (arg2) {
return `${arg2}`;
} else {
return arg1;
}
}
fn3('works');
fn3('also works', 5);
const fn4 = (arg: number): number => {
return arg;
};
type FnType = (arg: string) => number;
const fn5: FnType = (arg) => {
return parseInt(arg);
};
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// freezing objects
////////////////////////////////////////////////////////////////////////////////
const myUser = {
name: 'Sabrina',
};
myUser.name = 'Cynthia';
const myUnchangingUser = {
name: 'Fatma',
} as const;
// myUnchangingUser.name = 'Raîssa';
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// never
////////////////////////////////////////////////////////////////////////////////
const neverReturns = () => {
throw new Error('Always throws, never returns');
};
const myValue = neverReturns();
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Unions (or)
////////////////////////////////////////////////////////////////////////////////
type StringOrNumber = string | number;
type ProcessStates = 'open' | 'closed';
type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
const ProcessState: ProcessStates = 'open';
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// intersections (and)
////////////////////////////////////////////////////////////////////////////////
interface ErrorHandling {
success: boolean;
}
interface ArtworksData {
artworkName: string;
}
type APIResult = ArtworksData & ErrorHandling;
// more or less the same
interface AlsoAPIResult extends ErrorHandling {
artworkName: string;
}
const ArtworkResponse: APIResult = {
success: true,
artworkName: 'My art',
};
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// keyof
////////////////////////////////////////////////////////////////////////////////
type Point = { x: number; y: number };
const point: keyof Point = 'x';
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// typeof
////////////////////////////////////////////////////////////////////////////////
let original = { name: 'hello' };
type Copy = typeof original;
let innerCopy: Copy['name'];
// compine both!
const pointWithoutType = { x: 10, y: 10 };
const points: keyof typeof pointWithoutType = 'x';
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Structural type system (🦆 typing)
////////////////////////////////////////////////////////////////////////////////
interface Ball {
diameter: number;
}
interface Sphere {
diameter: number;
}
interface Tube {
diameter: number;
length: number;
}
let ball: Ball = { diameter: 10 };
let sphere: Sphere = { diameter: 20 };
let tube: Tube = { diameter: 12, length: 3 };
sphere = ball;
ball = sphere;
ball = tube;
// tube = ball;
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// discriminated type union
////////////////////////////////////////////////////////////////////////////////
type TimingEvent = { name: 'start'; userStarted: boolean } | { name: 'closed'; duration: number };
const handleEvent = (event: TimingEvent) => {
switch (event.name) {
case 'start':
console.log(event.userStarted);
break;
case 'closed':
console.log(event.duration);
}
};
//
//
//
//
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
// Generics
////////////////////////////////////////////////////////////////////////////////
function numberIdentity(arg: number): number {
return arg;
}
function stringIdentity(arg: string): string {
return arg;
}
function identity<Type>(arg: Type): Type {
return arg;
}
let output = identity<string>('myString');
// OR
output = identity('alsoString');
// Generic classess too
class GenericNumber<NumType> {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
return x + y;
};
//
//
//
//
//
//
//
//
//
//
//
interface USD {
_usdBrand: void;
value: number;
}
interface EUR {
_eurBrand: void;
value: number;
}
let usd = { value: 10 } as USD;
let eur = { value: 10 } as EUR;
function gross(net: USD, tax: USD) {
return { value: net.value + tax.value } as USD;
}
gross(usd, usd); // ok
// gross(eur, usd); // Error: Property '_usdBrand' is missing in type 'EUR'.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment