Skip to content

Instantly share code, notes, and snippets.

@lesleh
lesleh / toCamelCase.ts
Created June 2, 2023 10:35
TypeScript utilities to convert between cases
export type CamelCase<S extends string> =
S extends `${infer P1}_${infer P2}${infer P3}`
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
: Lowercase<S>;
export type ObjectToCamel<T> = {
[K in keyof T as CamelCase<string & K>]: T[K] extends Record<string, any>
? KeysToCamelCase<T[K]>
: T[K];
};
@lesleh
lesleh / currying.ts
Last active April 10, 2023 21:00
Function to auto-curry another function, with strong typing
interface Curry {
<T1, R>(func: (t1: T1) => R): CurriedFunction1<T1, R>;
<T1, T2, R>(func: (t1: T1, t2: T2) => R): CurriedFunction2<T1, T2, R>;
<T1, T2, T3, R>(func: (t1: T1, t2: T2, t3: T3) => R): CurriedFunction3<
T1,
T2,
T3,
R
>;
<T1, T2, T3, T4, R>(
@lesleh
lesleh / useFetch.test.ts
Created January 4, 2022 12:09
useFetch hook
import { renderHook } from '@testing-library/react-hooks';
import useFetch from '../useFetch';
function mockSuccessfulFetch(data) {
global.fetch = jest.fn().mockResolvedValue({
json: () => Promise.resolve(data),
});
}
function mockErrorFetch(error) {
@lesleh
lesleh / update.js
Last active September 1, 2022 14:13
/* eslint-disable no-restricted-syntax, no-console, no-await-in-loop */
const { promises: fs } = require("fs");
const { exec } = require("child_process");
const TEST_COMMANDS = [
"yarn check-types",
"yarn lint",
"yarn test",
"yarn build",
];
const isArray = function (a) {
return Array.isArray(a);
};
const isObject = function (o) {
return o === Object(o) && !isArray(o) && typeof o !== 'function';
};
const toCamel = s => (
s.replace(/([-_][a-z])/ig, $1 => $1.toUpperCase().replace(/[-_]/, ''))
@lesleh
lesleh / conversions.js
Last active March 31, 2020 11:08
Case conversion between camel case and snake case
const toCamel = (s) => {
return s.replace(/([-_][a-z])/ig, ($1) => {
return $1.toUpperCase()
.replace('-', '')
.replace('_', '');
});
};
const toSnake = (s) => {
return s.split(/(?=[A-Z])/).join('_').toLowerCase();
import React from 'react';
import useWindowEvent from './useWindowEvent';
function Example() {
useWindowEvent('keydown', (e) => {
console.log('Pressed', e.key);
});
return <div>Example</div>;
@lesleh
lesleh / remove-youtube-watched.js
Last active September 10, 2019 14:38
Delete watched YouTube videos from Watch Later. Only tested on the old layout.
const findVideos = () => [...document.querySelectorAll('.pl-video')];
const watchedGreaterThanHalf = (video) => {
const progressBar = video.querySelector('.resume-playback-progress-bar');
return progressBar && parseInt(progressBar.style.width) > 50;
}
const removeButton = (video) => x.querySelector('.pl-video-edit-remove');
const click = (button) => button.click();
@lesleh
lesleh / index.js
Created July 9, 2019 21:05
Lambda@Edge security headers
'use strict';
function addHeader(headers, key, value) {
if (!headers[key.toLowerCase()]) {
headers[key.toLowerCase()] = [{
key,
value,
}];
}
}
@lesleh
lesleh / adders.js
Last active September 16, 2018 20:45
// Lets say you have a function that creates adders, for adding two numbers
function makeAdder(firstNumber) {
return function(secondNumber) {
return firstNumber + secondNumber;
};
}
let result