/**
* TypeScript Utilities
*/
export type ValidValue<T> = Exclude<T, null | undefined | 0 | '' | false>
export type Optional<T> = T | undefined | null
/**
* Just like .filter(Boolean), but allows TypeScript to exclude falsy values in return type
* @example
* ```ts
* const x = [1, 2, 3, "", null, undefined, 0, false]
* const y = x.filter(BooleanFilter)
* // y is [1, 2, 3]
* ```
*/
export const BooleanFilter = <T,>(x: T): x is ValidValue<T> => Boolean(x)
export type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
/**
* Strings
*/
export function capitaliseFirstChar(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
export function enumToNiceString(str: string) {
const newStr = str
.replace(/_/g, ' ')
.replace(/([A-Z])/g, ' $1')
.trim()
.toLowerCase()
return str.charAt(0).toUpperCase() + str.slice(1)
}
/**
* Money
*/
export const formatMoneyCompact = (
currency: string | undefined,
amount: number,
) =>
new Intl.NumberFormat('en-GB', {
...(currency && {
style: 'currency',
currency: currency,
}),
notation: 'compact',
minimumFractionDigits: 0,
}).format(amount)
export const formatMoney = (currency: string | undefined, amount: number) => {
return new Intl.NumberFormat('en-GB', {
...(currency && {
style: 'currency',
currency: currency,
}),
minimumFractionDigits: 2,
currencyDisplay: 'narrowSymbol',
}).format(amount)
}
/**
* Cookies
*/
export const saveCookie = ({
key,
value,
maxAgeInSeconds = 30 * 24 * 60 * 60, // 30 days,
}: {
key: string
value: string | null
maxAgeInSeconds?: number
}): void => {
if (value === null) {
return
}
const domain = window?.location?.hostname?.split('.').slice(-2).join('.') // e.g. "blinkist.com"
document.cookie = `${key}=${value}; path=/; domain=.${domain}; max-age=${maxAgeInSeconds};`
}
export const getAllCookies = (): Record<string, string> | null => {
if (typeof window === 'undefined') {
return null
}
return document.cookie.split(';').reduce(
(acc, curr) =>
Object.assign(acc, {
[curr?.split('=')?.[0]?.trim() ?? '']: curr?.split('=')?.[1] ?? '',
}),
{},
)
}
export const getCookie = (key: string): string | null => {
return getAllCookies()?.[key] ?? null
}
/**
* Utils
*/
type Entries<T> = {
[K in keyof T]: [K, T[K]]
}[keyof T][]
export const getEntries = <T extends object>(obj: T) =>
Object.entries(obj) as Entries<T>
```
Resources (WIP 🏗️👷🏻♂️)
Links
Startup
Design Component Libraries
SEO
Typescript Goodies
type PropsWithChildren<P = unknown> = P & { children?: React.ReactNode }
PropsWithChildren
Landing page inspirations
My favorite blog posts
Startup
Typescript Goodies
- React type: PropsWithChildren
Tips
- Github -> .dev = editor
- https://x.com/_baretto/status/1828723629246341538
React type: PropsWithChildren
type PropsWithChildren<P> = P & { children?: ReactNode }
The best way to type icons
export const CheckedIcon = (props: SVGProps<SVGSVGElement>) => {
return (
<svg
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M10.7388 16.0732L7.00793 12.3423L7.97487 11.3731L10.7388 14.1371L16.5336 8.3446L17.5005 9.31154L10.7388 16.0732Z"
fill="currentColor"
/>
</svg>
)
}