Skip to content

Instantly share code, notes, and snippets.

@LevPewPew
Last active March 20, 2022 22:57
Show Gist options
  • Save LevPewPew/50a53190ac0123f649e9d1caac702573 to your computer and use it in GitHub Desktop.
Save LevPewPew/50a53190ac0123f649e9d1caac702573 to your computer and use it in GitHub Desktop.
KeysUnion custom utility type. create a union of strings out of keys in an interface where the value type match the given generic
// create union out of properties in an interface who'se value type match then given value types (can be given a union of types to match) #codesnippet
// Stack Overflow explanation https://stackoverflow.com/questions/54520676/in-typescript-how-to-get-the-keys-of-an-object-type-whose-values-are-of-a-given/66144780
export type KeysUnion<T, V> = { [K in keyof T]-?: T[K] extends V ? K : never }[keyof T];
// Playground
interface Cool {
ice: string;
cold: string;
}
interface Foobar {
fizz: string;
buzz: Cool;
}
interface FoobarWithNumbers {
fizz: string;
buzz: Cool;
apples: number;
}
const obj: Foobar = {
fizz: "test",
buzz: {
ice: "top",
cold: "kek"
}
}
const objWithApples: FoobarWithNumbers ={
fizz: "test",
buzz: {
ice: "top",
cold: "kek"
},
apples: 5
}
// should error
function someFunction0(someObj: Foobar, key: string) {
return someObj[key];
}
function someFunction1(someObj: Foobar, key: KeysUnion<Foobar, string>) {
return someObj[key];
}
// FIXME ideally this would error since there is no number value present in Foobar
function someFunction2(someObj: Foobar, key: KeysUnion<Foobar, number>) {
return someObj[key];
}
function someFunction2p1(someObj: Foobar, key: KeysUnion<FoobarWithNumbers, number>) {
return objWithApples[key];
}
function someFunction3(someObj: Foobar, key: KeysUnion<Foobar, any>) {
return someObj[key];
}
const x = someFunction1(obj, "fizz")
// should error
const y = someFunction1(obj, "nope")
// should error
const z = someFunction2(obj, "fizz")
const apples1 = someFunction2p1(objWithApples, "apples")
// should error
const fizz = someFunction2p1(objWithApples, "fizz")
// should error
const a = someFunction3(obj, "nope")
const b = someFunction3(obj, "fizz")
const c = someFunction3(obj, "buzz")
const explicitKey0: KeysUnion<Foobar, string> = "fizz"
// should fail
const explicitKey1: KeysUnion<Foobar, number> = "fizz"
// should fail
const explicitKey2: KeysUnion<Foobar, string> = "nope"
const explicitKey2p1: KeysUnion<FoobarWithNumbers, number> = "apples"
// should fail
const explicitKey3: KeysUnion<Foobar, string> = "buzz"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment