Home > Software design >  how can i make have the specific type infered based on argument passed
how can i make have the specific type infered based on argument passed

Time:12-03

I'd like to make it so that my get widget function result automatically returns the specific type based on the parameter I pass to the function. Is there a way to do this in typescript? As of right now it gives me one of the possible types as return but not the specific one corresponding to the key provided.

example

export interface ExampleAccountCenterHTMLElement extends HTMLElement {
    x: () => void;
}

export interface ExampleMiniFooterHTMLElement extends HTMLElement {
    y: () => void;
}

enum ExampleHtmlElementsName {
    ExampleMiniFooter = 'Example-mini-footer',
    ExampleAccountCenter = 'Example-account-center',
}

interface ExampleHtmlElements {
    [ExampleHtmlElementsName.ExampleAccountCenter]: ExampleAccountCenterHTMLElement,
    [ExampleHtmlElementsName.ExampleMiniFooter]: ExampleMiniFooterHTMLElement,
}

export function getWidget(tagName: ExampleHtmlElementsName) {
    return document.querySelector<ExampleHtmlElements[typeof tagName]>(tagName);
}

const res = getWidget(ExampleHtmlElementsName.ExampleAccountCenter)

CodePudding user response:

Using typeof on tagName is not a good idea. You gave tagName the explicit type ExampleHtmlElementsName, and that is excactly what typeof tagName will evaluate to. Instead, make the function generic.

export function getWidget<T extends ExampleHtmlElementsName>(tagName: T) {
    return document.querySelector<ExampleHtmlElements[T]>(tagName);
}

Playground

CodePudding user response:

Yes, you can use a type assertion to specify the return type of your function based on the provided tagName parameter. You can use the keyof operator to get the type of the keys in the ExampleHtmlElements interface, and then use this type to access the corresponding value in the ExampleHtmlElements interface. Here's an example of how you can do this:

export function getWidget(tagName: ExampleHtmlElementsName) {
    // Get the type of the keys in the ExampleHtmlElements interface
    type ElementKeys = keyof ExampleHtmlElements;

    // Use a type assertion to specify the return type based on the provided tagName parameter
    return document.querySelector<ExampleHtmlElements[ElementKeys]>(tagName) as ExampleHtmlElements[tagName];
}

In this example, the ElementKeys type is inferred to be ExampleHtmlElementsName, and the ExampleHtmlElements[tagName] expression evaluates to the type corresponding to the provided tagName value. This allows the compiler to check that the correct type is being returned based on the value of tagName.

  • Related