Skip to content

Instantly share code, notes, and snippets.

@mirhampt
Created July 20, 2020 17:12
Show Gist options
  • Save mirhampt/cb5c0a9bf704c860bc085159b4a2d2bc to your computer and use it in GitHub Desktop.
Save mirhampt/cb5c0a9bf704c860bc085159b4a2d2bc to your computer and use it in GitHub Desktop.
Typescript Conditional Types with "never"
/**
A (contrived) example of conditional types with `never`.
*/
/** Gets keys that have string values from object T. */
type StringPropertyNames<T> = {
[K in keyof T]: T[K] extends string ? K : never;
}[keyof T];
/**
Example usage recreating lodash `groupBy` function.
However, it only allows grouping by keys with string values.
This isn't super useful, but is a demonstration.
*/
export const groupBy = <T, K extends StringPropertyNames<T>>(
list: T[],
key: K
): { [k: string]: T[] } =>
list.reduce<{ [k: string]: T[] }>((acc, item) => {
const val = (item[key] as unknown) as string;
(acc[val] || (acc[val] = [])).push(item);
return acc;
}, {});
const places = [
{ city: "San Francisco", state: "California", date: new Date() },
{ city: "Bakersfield", state: "California", date: new Date() },
{ city: "Cleveland", state: "Ohio", date: new Date() },
{ city: "Cincinnati", state: "Ohio", date: new Date() },
];
const byState = groupBy(places, "state");
/**
Won't compile:
const byDate = groupBy(places, "date");
"Argument of type '"date"' is not assignable to parameter of type 'StringPropertyNames<{ city: string; state: string; date: Date; }>'"
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment