After holding out for a while hoping to stumble upon the solution, I've decided to give it a shot here on SO since I haven't found it yet.
import { PDFViewer, MSViewer } from './viewerclasses'
//attempting to incorporate a union of keys
type ViewerTypes = 'xls' | 'xlsx' | 'doc' | 'docx' | 'pdf';
type PreviewTypes = {
pdf: typeof PDFViewer;
doc: typeof PDFViewer;
docx: typeof PDFViewer;
xls: typeof MSViewer;
xlsx: typeof MSViewer;
}
const previewTypes: PreviewTypes = {
pdf: PDFViewer,
doc: PDFViewer,
docx: PDFViewer,
xls: MSViewer,
xlsx: MSViewer
};
//trial #1
type ViewerMap<T> = T extends ViewerTypes ? PreviewTypes[T] : false;
//trial #2
type ViewerMaybe<T> = T extends keyof PreviewTypes ? PreviewTypes[T] : false
export function getViewer<K extends ViewerTypes>(filename: K): ViewerMaybe<typeof filename> {
const type = (filename.split('.').pop()?.toLowerCase() as ViewerTypes) || 'unknown';
const viewer = Object.prototype.hasOwnProperty.call(previewTypes, type) === true
? previewTypes[type]
: false;
return viewer;
}
However, I'm just grasping at straws here, experimenting with different types in getViewer(), like mapped types and indexed access types, but TypeScript still isn't fully understanding my intent.
I am aiming to correctly type getViewer(), so that when I provide a key from previewTypes as an argument, I receive a constructor in return, and if not, then false. I have been circling around this issue for quite some time, but I am determined to gain a better grasp of the type system to resolve it. I recall there is a method to establish an indexed access type along the lines of
type ViewerIndexMap<T> = {
[Prop in keyof T]: Prop in keyof T ? T[Prop] : false
}
and subsequently,
export function getViewer(filename): ViewerIndexMap<typeof filename>
or something similar
Where am I faltering? What piece of the puzzle am I overlooking? Even after revisiting the TS handbook, I sense that although mapped types are close, they do not entirely align with my requirements.
Thank you!