DEV Community

Cover image for Which functions/methods do you...
JoelBonetR πŸ₯‡
JoelBonetR πŸ₯‡

Posted on • Edited on

Which functions/methods do you...

Which functions/methods do you copy from a project to another or re-code just to have them in some utils.js or utils.ts?

Latest comments (52)

Collapse
 
luiz0x29a profile image
Real AI

none, I publish my standard library to public repos and import it.

Collapse
 
alessandrocipolletti profile image
Alessandro Cipolletti • Edited

πŸ˜‚ I was recently wondering why should I keep doing that for every new project idea, so I made a ts npm package to just import my own code everywhere.

Take a look if you want: npmjs.com/package/js-math-and-ui-u...

I work a lot with animations and free-hand user input so one often use is getQuadraticBezierCurvePointAtTime:

getQuadraticBezierCurvePointAtTime

Collapse
 
jgomo3 profile image
JesΓΊs GΓ³mez

The identity function in any language that doesn't have it.

Collapse
 
himanshupal0001 profile image
Himanshupal0001

I see very experienced coders here. It would be great if anyone could guide me with my little project.πŸ₯²

Collapse
 
c_basso profile image
Vladimir Ivakhnenko

Function for prevent using try catch in all async await calls

type Result<DataType> = [
    Error | undefined,
    DataType | undefined
];

export const to = <DataType = any>(
    promise: Promise<DataType>
): Promise<Result<DataType>> => promise
    .then((data) => ([undefined, data]) as Result<DataType>)
    .catch((err: Error) => ([err, undefined]) as Result<DataType>);

Enter fullscreen mode Exit fullscreen mode

and use it like this

const [data, error] = await to(fetchData());

if (error) {
   console.error(error);
   return;
}

console.log(data);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kevinleebuchan profile image
KevinLeeBuchan

You should do a post on this. I use JavaScript all the time but I'm seeing syntax I'm not familiar with. I feel like I'm peeking through a window from a room I didn't know I was stuck in.

Collapse
 
joelbonetr profile image
JoelBonetR πŸ₯‡ • Edited

πŸ˜‚ Both @c_basso and @fedyk solutions are coded in TS that can be the cause of your confusion @kevinleebuchan, here's a JS translation (guys correct me if I miss something)

/**
 * Handles promise resolution
 * @param {Promise} promise
 * @returns {any}
 */
export const go = (promise) =>
  Promise.resolve(promise)
    .then((result) => [result, null])
    .catch((error) => [null, error]);
Enter fullscreen mode Exit fullscreen mode

Usage example:

/** Retrieves Ditto data */
const getDitto = async () => {
  const [result, error] = await go(fetch('https://pokeapi.co/api/v2/pokemon/ditto'));

  if (error) console.error(error);
  else console.log(await result.json());
};

await getDitto();
Enter fullscreen mode Exit fullscreen mode

Note that the return value of the go function is always an array with two positions, the first one intended to be a successful result, the second one reserved for the error so in case it succeeds it sends [result, null] and in case it fails it sends back [null, error], this may help to understanding:

const [result, error] = ['Success!', null];

result; // 'Success!'
error; // null
Enter fullscreen mode Exit fullscreen mode

Hope it helps! 😁

Collapse
 
fedyk profile image
Andrii Fedyk

to - funny name. I use similar helper, but I call it go. Here my recent post about it dev.to/fedyk/golang-errors-handing...

function go<T>(promise: T) {
  return Promise.resolve(promise)
    .then(result => [null, result] as const)
    .catch(err => [err, null] as const)
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mrdulin profile image
official_dulin

utils/ts-utility-types.ts:

export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

export type MaybeNull<T> = T | null;
export type MaybeUndefined<T> = T | undefined;
export type MaybeNil<T> = T | null | undefined;

export type AsyncFn = (...args: any[]) => Promise<any>;
export type AnyFn = (...args: any[]) => any;
export type UnboxPromise<T extends Promise<any>> = T extends Promise<infer U> ? U : never;

export type Nullable<T> = {
  [P in keyof T]: MaybeNull<T[P]>;
};
export type NullableBy<T, K extends keyof T> = Omit<T, K> & Nullable<Pick<T, K>>;

export type DistributedArray<U> = U extends any ? U[] : never;

/**
 * type ID = string | number;
 * type T0 = ID[];
 * type T1 = DistributedArray<ID>;
 * type EQ1 = IfEquals<T0, T1, 'same', 'different'>;  // different
 */
export type IfEquals<T, U, Y = unknown, N = never> = (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? Y : N;

export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;

export type ValueOf<T> = T[keyof T];
Enter fullscreen mode Exit fullscreen mode
Collapse
 
joelbonetr profile image
JoelBonetR πŸ₯‡

C'mon show us some functions 🀣🀣

I'm not sure about those TypeDefs honestly, I think it's better to have an inline, let's say:

const foo: string | null = 'whatever';
Enter fullscreen mode Exit fullscreen mode

so it's more clear for everyone than saying

const foo: MaybeNull<string> = 'whatever';
Enter fullscreen mode Exit fullscreen mode

but to keep the honesty in this comment, this is opinionated and I may be wrong πŸ˜…

Collapse
 
siddsarkar profile image
Siddhartha Sarkar

This is one I made and using across many projects.

/**
 * Takes full name and converts into initials
 * @param {string} string full name of user e.g John Doe
 * @returns initials e.g JD
 */
const getInitials = (string = '') =>
  string
    .split(' ')
    .map(([firstLetter]) => firstLetter)
    .filter((_, index, array) => index === 0 || index === array.length - 1)
    .join('')
    .toUpperCase()
Enter fullscreen mode Exit fullscreen mode
Collapse
 
joelbonetr profile image
JoelBonetR πŸ₯‡ • Edited

It seems a bit overcomplicated to me, I'd do something like:

const getInitials = (str = '') =>  str.split(' ').map( part => part.charAt(0).toUpperCase()).join('');
Enter fullscreen mode Exit fullscreen mode

I think it does the same but... Am I missing something maybe? Probably some use case that is not in my mind πŸ˜…

Collapse
 
siddsarkar profile image
Siddhartha Sarkar

You must restrict your initials to some letter count either one or two, see your initial from the above fn will grow with no. of words in a name which is not favourable to be called 'initials'

And yes my country surnames is at last so picking the last one in my code πŸ˜…

Collapse
 
kamil7x profile image
Kamil Trusiak

For input like Mary Jane Watson, your function returns MJW, and his returns MW.
It's common practice to use only two letters as initials on avatars (eu.ui-avatars.com/api/?name=Mary+J...)

Thread Thread
 
joelbonetr profile image
JoelBonetR πŸ₯‡ • Edited

That was one of my first thoughts but initials depend on the country, so my name is Joel Bonet Rxxxxx, being Joel my name and Bonet + Rxxxxx my two surnames.
So in this case I'll be JR with this approach which in my country and according to my culture or what is reasonable, it should be JB. (first character of the name + first character of the surname).

That's the main reason for getting separate fields for name and surname/s.

So your name can be "Mary Jane Linda" and your surnames can be "Lee Bonet".

const initials = `${user.name.charAt(0).toUpperCase()}${user.surname.charAt(0).toUpperCase()}`; 
Enter fullscreen mode Exit fullscreen mode

and still getting ML as initials which would be the most correct output as far as I can tell.

Thread Thread
 
kevinleebuchan profile image
KevinLeeBuchan

Here I am enjoying all the great, open conversations about programming and now I learn something about other cultures too. #Winning

Collapse
 
lionelrowe profile image
lionel-rowe

Here are a few of the more generally useful ones:

const isSameOrigin = (url: string) =>
    new URL(url, window.location.href).origin === window.location.origin

const isTouchDevice = window.matchMedia('(pointer: coarse)').matches
const isMobile = navigator.userAgent.includes('Mobi')

const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1)

const decodeBase64 = (base64: string) =>
    new TextDecoder().decode(new Uint8Array(atob(base64).split('').map((char) => char.charCodeAt(0))))

const encodeBase64 = (str: string) =>
    btoa(Array.from(new TextEncoder().encode(str))
        .map((n) => String.fromCharCode(n))
        .join(''))

const xor = (...args: any[]) =>
    args.filter(Boolean).length === 1
Enter fullscreen mode Exit fullscreen mode
Collapse
 
joelbonetr profile image
JoelBonetR πŸ₯‡

Those are currently very useful ones!

I've a slightly different base64encode one

/**
 * encodes a file into base64
 * @param {import('fs').PathOrFileDescriptor} fileOrigin
 * @returns {string}
 */
function base64_encode(fileOrigin) {
  /** @type {Buffer} */
  const file = fs.readFileSync(fileOrigin);
  return Buffer.from(file).toString('base64');
}
Enter fullscreen mode Exit fullscreen mode

I'll check the differences later 😁

Collapse
 
brunnerlivio profile image
Livio Brunner • Edited

The base64 functions from @lionel-rowe are compatible with (most) browser. The fs module is only available in Node.js :)

Thread Thread
 
joelbonetr profile image
JoelBonetR πŸ₯‡ • Edited

Of course but what I want to check is the details on what's happening on this TextDecoder(), it's decode method and also the reason for it to use an array of 8-bit unsigned integers πŸ˜‚

Thread Thread
 
lionelrowe profile image
lionel-rowe

TextEncoder and TextDecoder convert strings to and from their equivalent UTF-8 bytes. So for example, new TextEncoder().encode('foo 福 🧧') gives Uint8Array [102, 111, 111, 32, 231, 166, 143, 32, 240, 159, 167, 167], where bytes 0..2 represent the 3 ASCII characters "foo", 4..6 represent the single 3-byte character "福", and 8..11 represent the single 4-byte character "🧧" (3 and 7 are spaces).

Thread Thread
 
joelbonetr profile image
JoelBonetR πŸ₯‡

Thanks you for the explanation! 😁

Collapse
 
ajinspiro profile image
Arun Kumar

let callApi=(path) => fetch(path).then(response => response.json())

Collapse
 
siddsarkar profile image
Siddhartha Sarkar

This is my favourite one and universal too:

/**
 * Global network request handler
 * @param {RequestInfo} url url to fetch
 * @param {RequestInit=} options fetch options
 * @returns json response
 */
const processFetchRequest = async (url, options) => {
  const ts = Date.now();
  const method = options?.method || 'GET';
  const endpoint = url.match(
    /((?!\S+\s)?\S*[/].*?(?:\S+\s)?\S*[/])([\s\S]*)/,
  )[2];

  const response = await fetch(url, options);
  console.log(`${method}${response.status}: ${Date.now() - ts}ms /${endpoint}`);

  if (response.ok) {
    return response.json();
  }
  throw response.json();
};

export default processFetchRequest;
Enter fullscreen mode Exit fullscreen mode
Collapse
 
joelbonetr profile image
JoelBonetR πŸ₯‡

This will work just for GET requests without authentication, let me do a little tweak on it by just adding an optional "options" parameter 😁

services/api/utils.js

const requestBuilder = (path, options) => fetch(path, options).then(response => response.json()).catch(error => error)
Enter fullscreen mode Exit fullscreen mode

now you can perform any HTTP verb request on a new layer of functions like

PUT example (POST will look mostly the same):
services/api/users.js:

const updateUser = (user) => requestBuilder( Process.env.API_URL, {  
  method: 'PUT',
  body: JSON.stringify(user),
  headers: {
    'Content-Type': 'application/json',
    Authorization: getToken(),
  },
}).then( result => result);
Enter fullscreen mode Exit fullscreen mode

Working example

You can try it in your browser terminal right now:

services/api/pokemon.js:

const getPokemonByName = (pokemon) =>requestBuilder(`https://pokeapi.co/api/v2/pokemon/${pokemon}`, { method: 'GET' })
Enter fullscreen mode Exit fullscreen mode

usage:

getPokemonByName('ditto')
Enter fullscreen mode Exit fullscreen mode
Collapse
 
moopet profile image
Ben Sinclair • Edited

I don't really have snippets I reuse. I might occasionally pinch a function from another project, but there's nothing I can think of that would be worth a snippet, and I've never really remembered to use them when I've tried.

I do have these vim mappings for older PHP projects which don't have much in the way of development tools:

autocmd FileType php nnoremap <buffer> <leader>dump Oheader('X-XSS-Protection:0');ob_get_clean(); echo '<pre>'; var_dump([]); echo '</pre>'; die(__FILE__ . ':' . __LINE__);<esc>F[a
autocmd FileType php nnoremap <buffer> <leader>args Oheader('X-XSS-Protection:0');ob_get_clean(); echo '<pre>'; var_dump(func_get_args()); echo '</pre>'; die(__FILE__ . ':' . __LINE__);<esc>F[a
autocmd FileType php nnoremap <buffer> <leader>back Oheader('X-XSS-Protection:0');ob_get_clean(); echo '<pre>'; foreach (debug_backtrace() as $d) { echo $d['file'] . ':' . $d['line'] . ' ' . $d['function'] . "()\n"; } echo '</pre>'; d  ie(__FILE__ . ':' . __LINE__);<esc>^
Enter fullscreen mode Exit fullscreen mode

They'll let me paste in a variable dump with my cursor positioned where I need to put in the thing to debug, or a generic stack trace. They also cope with frameworks that do tricky things with output buffering.

That's about it.