Last active
May 18, 2022 21:30
-
-
Save a7madgamal/11c4ec4fbb8a36b16ed2f269c34676ab to your computer and use it in GitHub Desktop.
Typescript intro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////// | |
// 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