Skip to content

Instantly share code, notes, and snippets.

@zachhardesty7
Last active February 29, 2024 21:31
Show Gist options
  • Save zachhardesty7/b1d6650475c0b30dc57eebe13d20ae37 to your computer and use it in GitHub Desktop.
Save zachhardesty7/b1d6650475c0b30dc57eebe13d20ae37 to your computer and use it in GitHub Desktop.
TS: isTruthy
// copyright 2023 Zach Hardesty
// want to check this out in the TypeScript playground?
// visit the following link to automatically see the latest version!
// https://www.typescriptlang.org/play?jsx=0#gist/b1d6650475c0b30dc57eebe13d20ae37
/**
* Type guard helper for checking if a value is truthy. mostly for use with
* {@link Array.prototype.filter} to clean up array types
*
* @example
* const foo = true
* const bar = false
* const baz = [foo && "string1", bar && "string2"]
* console.log(baz.filter(isTruthy))
* // => ["string1"]
* // boolean is removed from type of baz and it becomes string[]
*
* @param input - Value to check
* @see https://stackoverflow.com/a/19839953/5299167 for a list of falsey values
*/
function isTruthy<T>(
input: T,
): input is T extends undefined | null | false | "" | 0 | 0n ? never : T {
return !!input;
}
const x0_0 = ([true, false] as const).filter(isTruthy);
type T0_0 = Expect<typeof x0_0, true[]>;
const x1_0 = ([1, 0, 0.0, -0, 0x0] as const).filter(isTruthy);
type T1_0 = Expect<typeof x1_0, 1[]>;
const x2_0 = ([{}, undefined, null] as const).filter(isTruthy);
type T2_0 = Expect<typeof x2_0, {}[]>;
const x3_0 = (["truthy", "", ``] as const).filter(isTruthy);
type T3_0 = Expect<typeof x3_0, "truthy"[]>;
const x4_0 = ([1n, 0n, 0x0n] as const).filter(isTruthy);
type T4_0 = Expect<typeof x4_0, 1n[]>;
const x5_0 = ([0, false] as const).filter(isTruthy);
type T5_0 = Expect<typeof x5_0, never[]>;
const x6_0 = ([true, NaN, Number.NaN] as const).filter(isTruthy);
// @ts-expect-error - no literal type for NaN, so impossible to remove `number` from result type
type T6_0 = Expect<typeof x6_0, true[]>;
const x7_0 = ([] as never[]).filter(isTruthy);
type T7_0 = Expect<typeof x7_0, never[]>;
const v010 = Math.random() > 0.5 ? "a" : undefined;
if (isTruthy(v010)) {
type T010 = Expect<typeof v010, "a">;
} else {
type T010 = Expect<typeof v010, undefined>;
}
const v020 = Math.random() > 0.5 ? "a" : false;
if (isTruthy(v020)) {
type T020 = Expect<typeof v020, "a">;
} else {
type T020 = Expect<typeof v020, false>;
}
const v030 = Math.random() > 0.5 ? "a" : Math.random() > 0.5 ? "" : false;
if (isTruthy(v030)) {
type T030 = Expect<typeof v030, "a">;
} else {
type T030 = Expect<typeof v030, false | "">;
}
type Result = "ACK" | "ERR" | "";
declare const result: Result;
if (result) {
console.log("🚀 ~ result:", result);
// handle that a result was received
} else {
console.log("🚀 ~ result:", result);
// couldn't get a result
}
/** @see https://gist.github.com/zachhardesty7/1b5b6f6de328f1bb7c78cbe96ba5c720 */
type Expect<
TInput extends TIntersect,
TExpected extends TIntersect,
TIntersect = TExpected & TInput,
> = TInput;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment