types-spring icon indicating copy to clipboard operation
types-spring copied to clipboard

Consider adding safe Record type

Open Dimava opened this issue 1 year ago • 5 comments

interface RecordConstructor {
	new <K extends PropertyKey = PropertyKey, T = unknown>(): Record<K, T>;
	new <K extends PropertyKey, T>(entries: [K, T][]): Record<K, T>;
	keys<O extends Record<any, any>>(o: O): keyof O[];
	values<O extends Record<any, any>>(o: O): O[keyof O];
	entries<O extends Record<any, any>>(o: O): { [K in keyof O]-?: [K, O[K]] }[keyof O];
	fromEntries<T extends new () => Record<any, any>, K extends PropertyKey, V>(this: T, o: [K, V][]): Record<K, V>;
}
export const Record: RecordConstructor = class Record<K extends string | number | symbol, T> {
        constructor(entries?: [K, T][]){ /* ... */ }
	static keys<O extends Record<any, any>>(o: O) { return Object.keys(o) }
	static values<O extends Record<any, any>>(o: O) { return Object.values(o) }
	static entries<O extends Record<any, any>>(o: O) { return Object.entries(o) }
	static fromEntries<T extends new () => Record<any, any>>(this: T, o: [any, any][]) {
		return Object.assign(new this(), Object.fromEntries(o))
	}
} as any; // or a function with null prototype to remove prototype entirely, or Object.setPrototypeOf(this, null) in constructor
Object.setPrototypeOf(Record.prototype, null);
delete Record.prototype.constructor
// maybe also export type Record<K extends string | number | symbol, T> = ...; if import would override global Record type

this makes user able to use proper records, without caring about o.constructor and o.__proto__ breaking the expected behaviour, and using Record.keys() on objects user believes to be records

Dimava avatar Jun 07 '23 13:06 Dimava