Skip to content

Commit

Permalink
2024-02-22: Supernatural: I’ll interrogate the code
Browse files Browse the repository at this point in the history
- start code examples
  • Loading branch information
e-kulikov committed Feb 27, 2024
1 parent ad298c2 commit 1b8bd87
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 2 deletions.
35 changes: 35 additions & 0 deletions 2024-02-22_superstitious-programming/1-undefined.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const customer: { dob?: Record<string, any> } = {};

// 1. Object property check
{
// before
if (typeof customer.dob !== 'undefined') {
customer.dob.constructed = new Date().toLocaleDateString();
}

// after
if (customer.dob !== undefined) {
customer.dob.constructed = new Date().toLocaleDateString();
}
/*
It used to be that `undefined` was a global variable that could be reassigned.
Nowadays, it's impossible. Don't be superstitious, you shouldn't use bulky constructions with `typeof` checks
*/
}

// 2. Global variable check
{
// before
if (typeof customerDoB !== 'undefined') {
customerDoB = new Date().toLocaleDateString()
}
// after
// there is no "after" for this construction ¯\_(ツ)_/¯, thanks to TypeScript

/*
There was a case when we check the value of global variable, that might not be declared, and that causes an error.
If you are not sure if the global variable exists, it's better check it explicitly (using `if ('varname' in global)`).
Don't be superstitious, TypeScript highlights cases like this and protects you from accessing non-declared variables.
*/
}
28 changes: 28 additions & 0 deletions 2024-02-22_superstitious-programming/2-catch-throw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
declare function saveQuotes(quotes: any): void;

// before
{
const doQuotes = async () =>
fetch('http://localhost:3000')
.then((quotes) => {
saveQuotes(quotes)
})
.catch((err) => {
throw new Error(err);
});

// When I see code like this, I imagine a developer who thinks "I bet I can throw the error much further than `fetch` does"
}

// after
{
const doQuotes = async () =>
fetch('http://localhost:3000')
.then((quotes) => {
saveQuotes(quotes)
})

/*
Don't be superstitious, if you are not going to process the error somehow (log, enrich or trace it), don't catch-throw error
*/
}
31 changes: 31 additions & 0 deletions 2024-02-22_superstitious-programming/3-default-assign.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
// before
class HTTPError extends Error {
status: number;
constructor(status: number, message: string | undefined = undefined) {
super(message);
this.status = status;
}
}

/*
Most likely, the developer who wrote this had just started using TypeScript and default assignment feature.
That's why it's really important to know you job well :)
*/
}

{
// after
class HTTPError extends Error {
status: number;
constructor(status: number, message?: string) {
super(message);
this.status = status;
}
}

/*
In TypeScript, there is much more elegant way to make the variable optional, using question mark before type assignment.
And don't be superstitious, any variable in JavaScript (superset of which TypeScript is) is `undefined` by default.
*/
}
10 changes: 10 additions & 0 deletions 2024-02-22_superstitious-programming/4-return.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type MiddlewareFunction = (req: Record<string, any>, res: unknown, next: (a: any) => void) => void;
declare function isTokenValid(token: any): Promise<boolean>
export const authenticate : MiddlewareFunction = (req, res, next) : void => {
try {
const isValid = await isTokenValid(req.headers.Authorization);
!isValid && next(new Error(401));
} catch (err) {
next(new UnauthorizedError(err.message));
}
};
Empty file.
11 changes: 11 additions & 0 deletions 2024-02-22_superstitious-programming/6-promise2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const data = [0, 1, 2, 3];

function getAsyncData(key): Promise<{}> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(data[key]);
}, 1000)
})
}

await getAsyncData(0)
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */

/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "esnext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
Expand All @@ -25,7 +25,7 @@
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */

/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"module": "nodenext", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
Expand Down

0 comments on commit 1b8bd87

Please sign in to comment.