Last active
September 30, 2021 08:33
-
-
Save yackinn/fa9fa44f672ec294dbd80607ddd27e38 to your computer and use it in GitHub Desktop.
Create dictionary function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { isFunction } from 'lodash-es'; | |
// todo may remove SymbolConstructor.iterator from item type | |
// record callbacks | |
type CallbackRecord<SourceItem, SourceKey, DictItem, DictKey> = | |
(item: SourceItem, key: SourceKey, index: number) => [DictKey, DictItem] | |
// array callbacks | |
type CallbackArray<SourceItem, DictItem, DictKey> = | |
(item: SourceItem, index: number) => [DictKey, DictItem] | |
// Combined | |
// type DictCallback<SourceItem, SourceKey, DictItem, DictKey> = | |
// CallbackRecord<SourceItem, SourceKey, DictItem, DictKey> | |
// | CallbackArray<SourceItem, DictItem, DictKey> | |
// todo RecordKey should also account for enum keys; any is needed as of today as it allows for enum keys | |
// https://github.com/Microsoft/TypeScript/pull/26797 | |
// record or array without target | |
export function createDictionary<SourceItem, | |
SourceKey extends PropertyKey, | |
Source extends SourceItem[] | Record<SourceKey, SourceItem>, | |
DictItem, | |
DictKey extends PropertyKey>( | |
arrayOrRecord: Source, | |
callback: Source extends SourceItem[] | |
? CallbackArray<InferArrayValue<Source>, DictItem, DictKey> | |
: CallbackRecord<InferRecordValue<Source>, keyof Source, DictItem, DictKey> | |
): Record<DictKey, DictItem>; | |
// record or array with target | |
export function createDictionary<SourceItem, | |
SourceKey extends PropertyKey, | |
Source extends SourceItem[] | Record<SourceKey, SourceItem>, | |
TargetDictItem, | |
TargetDictKey extends PropertyKey>( | |
arrayOrRecord: Source, | |
target: Record<TargetDictKey, TargetDictItem>, | |
callback: Source extends SourceItem[] | |
? CallbackArray<InferArrayValue<Source>, TargetDictItem, TargetDictKey> | |
: CallbackRecord<InferRecordValue<Source>, keyof Source, TargetDictItem, TargetDictKey> | |
): Record<TargetDictKey, TargetDictItem>; | |
export function createDictionary<SourceItem, | |
SourceKey extends PropertyKey, | |
Source extends SourceItem[] | Record<SourceKey, SourceItem>, | |
TargetDictItem, | |
TargetDictKey extends keyof TargetDict, | |
TargetDict extends Record<TargetDictKey, TargetDictItem> | |
| CallbackArray<SourceItem, InferRecordValue<TargetDict>, TargetDictKey> | |
| CallbackArray<SourceItem, DictItem, DictKey> | |
| CallbackRecord<SourceItem, keyof Source, InferRecordValue<TargetDict>, TargetDictKey> | |
| CallbackRecord<SourceItem, keyof Source, DictItem, DictKey>, | |
DictItem, | |
DictKey extends PropertyKey>( | |
arrayOrRecord: Source, | |
targetOrCallback: TargetDict, | |
callback?: Source extends SourceItem[] | |
? TargetDict extends Record<any, any> | |
? CallbackArray<SourceItem, InferRecordValue<TargetDict>, TargetDictKey> | |
: CallbackArray<SourceItem, DictItem, DictKey> | |
: TargetDict extends Record<any, any> | |
? CallbackRecord<SourceItem, keyof Source, InferRecordValue<TargetDict>, TargetDictKey> | |
: CallbackRecord<SourceItem, keyof Source, DictItem, DictKey> | |
): Record<DictKey, DictItem> | TargetDict { | |
if (!arrayOrRecord) { | |
return; | |
} | |
let dictionary; | |
if (isFunction(targetOrCallback)) { | |
callback = targetOrCallback; | |
dictionary = {} as Record<DictKey, DictItem>; | |
} | |
else { | |
dictionary = targetOrCallback as TargetDict; | |
} | |
if (isArray(arrayOrRecord) && isFunction(targetOrCallback)) { | |
arrayOrRecord.forEach((item, index) => { | |
const result = callback(item, index); | |
dictionary[result[0]] = result[1]; | |
}); | |
} | |
else { | |
Object.entries<SourceItem>(arrayOrRecord).forEach(([key, item], index) => { | |
const result = callback(item, key, index); | |
dictionary[result[0]] = result[1]; | |
}); | |
} | |
return dictionary; | |
} | |
// function isDictCallback(item): item is DictCallback<any, any, any, any> { | |
// return isFunction(item); | |
// } | |
export function dictionary<K extends PropertyKey, T>(): Record<K, T> { | |
return {} as Record<K, T>; | |
} | |
export function isArray<T>(value: T[] | Record<PropertyKey, T>): value is T[] { | |
return Array.isArray(value); | |
} | |
export function isRecord<T>(value: T[] | Record<PropertyKey, T> | ((...any: any) => any)): value is Record<any, any> { | |
return !Array.isArray(value) && !isFunction(value); | |
} | |
type InferArrayValue<T> = T extends Array<infer U> ? U : T; | |
type InferRecordValue<T> = T extends Record<any, infer U> ? U : T |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment