Skip to content

Instantly share code, notes, and snippets.

@zachhardesty7
Last active December 3, 2024 00:12
Show Gist options
  • Select an option

  • Save zachhardesty7/63e56cd69e55a659120ec1e95a380a1e to your computer and use it in GitHub Desktop.

Select an option

Save zachhardesty7/63e56cd69e55a659120ec1e95a380a1e to your computer and use it in GitHub Desktop.
TS: KeysAssignableType
// copyright 2023 Zach Hardesty
// TODO: check out https://www.totaltypescript.com/get-keys-of-an-object-where-values-are-of-a-given-type
/**
* Extracts keys of `TObj` that correspond to values that some type in the union
* `TTypes` can be assigned to
*
* @template TObj Object to extract keys from
* @template TTypes Type to check for assignability
* @returns Union of keys of `TObj` that correspond to values that `TTypes` can be
* assigned to
*/
type KeysAssignableType<TObj, TTypes> = {
[P in keyof Required<TObj>]: TTypes extends Required<TObj>[P] ? P : never;
}[keyof TObj];
type KeysAssignableExactType<TObj, TTypes> = {
[P in keyof Required<TObj>]: [TTypes] extends [Required<TObj>[P]] ? P : never;
}[keyof TObj];
interface ITestObj1 {
a: string;
b: number;
c?: string;
d?: number;
e: boolean;
f: string | number;
g: undefined;
h: null;
i?: never;
j: unknown;
k: any;
l: { a: string };
m: "a" | "b";
}
type T0_0 = Expect<KeysAssignableType<ITestObj1, string>, "a" | "c" | "f" | "j" | "k">;
type T1_0 = Expect<
KeysAssignableType<ITestObj1, string | number>,
"a" | "b" | "c" | "d" | "f" | "j" | "k"
// REVIEW: more appropriate stricter type?
// "f" | "j" | "k"
>;
type T2_0 = Expect<KeysAssignableType<ITestObj1, any>, keyof ITestObj1>;
type T3_0 = Expect<KeysAssignableType<ITestObj1, object>, "j" | "k">;
type T4_0 = Expect<KeysAssignableType<{}, any>, never>;
type T5_0 = Expect<
KeysAssignableType<ITestObj1, { a: string; b: number }>,
"j" | "k" | "l"
>;
type T6_0 = Expect<
KeysAssignableType<ITestObj1, "a">,
"a" | "c" | "f" | "j" | "k" | "m"
>;
type T7_0 = Expect<
KeysAssignableType<ITestObj1, "a" | "b" | "c">,
"a" | "c" | "f" | "j" | "k" | "m"
// REVIEW: more appropriate stricter type?
// "a" | "c" | "f" | "j" | "k"
>;
type T8_0 = Expect<
KeysAssignableType<ITestObj1, "a" | number>,
"a" | "b" | "c" | "d" | "f" | "j" | "k" | "m"
>;
/** @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