Search code examples
typescripttypestype-conversionbackendphantomjs

Extract string literal type of an interface's function's arguments


In @types/phantom, there is a WebPage interface, which includes the following function:

interface WebPage {
    // ...
    property(
        key:
            | "content"
            | "plainText"
            | "focusedFrameName"
            | "frameContent"
            | "frameName"
            | "framePlainText"
            | "frameTitle"
            | "libraryPath"
            | "offlineStoragePath"
            | "title"
            | "url"
            | "windowName",
    ): Promise<string>;
}

I'm trying to extract the property of "key" and use it in a generic.

I'm expecting the following:

async getPageProperty<T extends Parameters<WebPage["property"]>[0]>(url: string, property: T){
   // ...
}

to interpret the the "key" argument's type as "content" | "plainText" | "focusedFrameName" | ... , but, to my surprise, I get:

(type parameter) T in PhantomJS.getPageProperty<T extends string>(url: string, property: T): Promise<T> .

Is there any way to correctly type T as the string literal instead of just "string" ?


Solution

  • What you did is correct if that were the only signature of the function. The problem is that the types for phantom have multiple overloads for property, not just the one that you provide. Thus, the extracted type is the union of all of those possible types of key, and some of them have key as simply string.

        property(key: "framesName" | "pagesWindowName" | "pages"): Promise<string[]>;
        property(key: "canGoBack" | "canGoForward" | "navigationLocked" | "ownsPages"): Promise<boolean>;
        property(key: "framesCount" | "offlineStorageQuota" | "zoomFactor"): Promise<number>;
        property(key: "clipRect"): Promise<{
            top: number;
            left: number;
            width: number;
            height: number;
        }>;
        property(key: "cookies"): Promise<ICookie[]>;
        property(key: "customHeaders"): Promise<{ [key: string]: string }>;
        property(key: "paperSize"): Promise<IPaperSizeOptions>;
        property(key: "scrollPosition"): Promise<{ top: number; left: number }>;
        property(key: "viewportSize"): Promise<{ width: number; height: number }>;
        property<T>(key: string): Promise<T>;
        property<T>(key: string, value: T): Promise<void>;
    

    https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ced533042db1b1663be0397fca6e2382dbcbf263/types/phantom/index.d.ts#L196-L226