Skip to content

Instantly share code, notes, and snippets.

@zachhardesty7
Last active March 10, 2023 20:36
Show Gist options
  • Save zachhardesty7/63e56cd69e55a659120ec1e95a380a1e to your computer and use it in GitHub Desktop.
Save zachhardesty7/63e56cd69e55a659120ec1e95a380a1e to your computer and use it in GitHub Desktop.
TS: KeysAssignableType
// 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/63e56cd69e55a659120ec1e95a380a1e
/**
* 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