TypeScript, Understanding the code you write
:-====-:
-+-. .:-+**-
+= =+:...-*+
:* == := *:
:* == -+. *:
:* .**- :+-
:* -+- :+-
:*-+- :+++.
:*- :+= :+=.
:* -+:+= :*.
:* +- == *:
*: :*: .=*.
.+=. .-===+*+.
:===--===:
- How it works
- Narrowing
- keyof operator
- in operator
- Generics
- Mapped Types
- as const
- typescript coverage
- Practice
Browsers Cannot understand TypeScript
~~~graph-easy --as=boxart
[ TYPESCRIPT ] - Compilation/Transpiling -> [ JAVASCRIPT ]
~~~
~~~graph-easy --as=boxart
[ const a: number = 5; ] - Compilation/Transpiling -> [ const a = 5; ]
~~~
TS VS. C#
Compile Time VS. Runtime
Function Overload in C#
void display() { ... }
void display(int a) { ... }
float display(double a) { ... }
float display(int a, float b) { ... }
Typescript is gone before Runtime
Function Overload in Typescript
// typescript
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
// javascript
function makeDate(mOrTimestamp, d, y) {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
}
else {
return new Date(mOrTimestamp);
}
}
Typescript is gone before Runtime
Function Overload in Typescript
// typescript
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
// javascript
function makeDate(mOrTimestamp, d, y) {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
}
else {
return new Date(mOrTimestamp);
}
}
Typescript is gone before Runtime
Function Overload
// typescript
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
// javascript
function makeDate(mOrTimestamp, d, y) {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
}
else {
return new Date(mOrTimestamp);
}
}
Zod Runtime Typechecking
for TypeScript
TS determines the variable type from the code context
function example(x: string | number, y: string | boolean) {
if (x === y) {
x.toUpperCase();
y.toLowerCase();
} else {
console.log(x);
console.log(y);
}
}
TS determines the variable type from the code context
function example(x: string | number, y: string | boolean) {
if (x === y) {
// We can now call any 'string' method on 'x' or 'y'.
x.toUpperCase();
// (method) String.toUpperCase(): string
y.toLowerCase();
// (method) String.toLowerCase(): string
} else {
console.log(x);
// (parameter) x: string | number
console.log(y);
// (parameter) y: string | boolean
}
}
The inoperator narrowing
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
animal;
} else {
animal;
}
}
The inoperator narrowing
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
animal;
// (parameter) animal: Fish | Human
} else {
animal;
// (parameter) animal: Bird | Human
}
}
instanceofnarrowing
function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toUTCString());
} else {
console.log(x.toUpperCase());
}
}
instanceofnarrowing
function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toUTCString());
// (parameter) x: Date
} else {
console.log(x.toUpperCase());
// (parameter) x: string
}
}
instanceofnarrowing
function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toUTCString());
// (parameter) x: Date
} else {
console.log(x.toUpperCase());
// (parameter) x: string
}
}
Extract keys
or properties of a typein a union format
if no object then never
will be returned
const scheduler = {
id: 2,
name: "Test",
internalCategoryId: 4,
}
We need to extract the scheduler
keys
// Result
type schedulerKeys = "id" | "name" | "internalCategoryId";
const scheduler = {
id: 2,
name: "Test",
internalCategoryId: 4,
}
type schedulerType = typeof scheduler
type schedulerKeys = keyof schedulerType
const scheduler = {
id: 2,
name: "Test",
internalCategoryId: 4,
}
type schedulerType = typeof scheduler
type schedulerKeys = keyof schedulerType
type namesIdsLists = {
picker: FilterOption[];
deliveryPerson: FilterOption[];
internalCategory: FilterOption[];
fp: FilterOption[];
}
type namesIdsLists = {
picker: FilterOption[];
deliveryPerson: FilterOption[];
internalCategory: FilterOption[];
fp: FilterOption[];
}
type listTypes = "picker" | "deliveryPerson" | "internalCategory" | "fp";
type namesIdsLists = {[k in listTypes]: FilterOption[]}
Think of it like function
in TS
interface BasicType {
input: string;
}
const x: BasicType = { input: "test" };
Think of it like function
in TS
interface BasicType<T> {
input: T;
}
const x: BasicType<string> = { input: "test" };
const y: BasicType<number> = { input: "test" }; // wrong
Think of it like function
in TS
function basic(a, b) {
return { a, b };
}
Think of it like function
in TS
function basic<A, B>(a, b) {
return { a, b };
}
Think of it like function
in TS
function basic<A, B>(a: A, b: B) {
return { a, b };
}
Think of it like function
in TS
function basic<A, B>(a: A, b: B): {a: A, b: B} {
return { a, b };
}
basic<string, number>("hello", 2);
[If] Condition
function isNumber(item) {
if(typeof item === 'number') return true;
return false
}
[If] Condition
type IsNumber<T> = T extends number ? true : false;
function isNumber<T>(item: T): IsNumber<T> {
if(typeof item === 'number') return true;
// Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)
return false;
// Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)
}
[If] Condition
type IsNumber<T> = T extends number ? true : false;
function isNumber<T>(item: T): IsNumber<T> {
if(typeof item === 'number') return true as IsNumber<T>;
// Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)
return false as IsNumber<T>;
// Type 'boolean' is not assignable to type 'IsNumber<T>'.(2322)
}
[If] Condition
type IsNumber<T> = T extends number ? true : false;
function isNumber<T>(item: T): IsNumber<T>
function isNumber(item: number): true
function isNumber<T>(item: number) {
if(typeof item === 'number') return true;
return false;
}
map
ped types
Object.freeze
in compile time
Note: Object.freeze
only top level, but const assertion
entire object
const x = [1,2];
// typeof x -> number[]
const x = [1,2] as const;
// typeof x -> readonly [1,2]
Notes on TypeScript
___ _ _ ___
/ _ \ _ _ ___ ___ | |_ (_) ___ _ __ ___|__ \
| | | || | | | / _ \/ __|| __|| | / _ \ | '_ \ / __| / /
| |_| || |_| || __/\__ \| |_ | || (_) || | | |\__ \|_|
\__\_\ \__,_| \___||___/ \__||_| \___/ |_| |_||___/(_)
_____ _ _
|_ _|| |__ __ _ _ __ | | __ ___
| | | '_ \ / _` || '_ \ | |/ // __|
| | | | | || (_| || | | || < \__ \
|_| |_| |_| \__,_||_| |_||_|\_\|___/