javascripttypescripttypescript-declarations

Return type of function properties in typescript declaration


I'm trying to fix the Typescript declaration for youtube-dl-exec, which has a default export which is a function with properties. In short, the default export returns a promise, alternatively you can call the exec() method which returns a child process so you can monitor the progress without waiting for the promise to resolve.

The existing declaration works for the default function, but not any of the properties:

import ytdl from 'youtube-dl-exec';
const p = ytdl('https://example.com'); // p is Promise<YtResponse>
const r = ytdl.exec('https://example.com'); // r should be ExecaChildProcess
// ^ property exec does not exist … ts(2339)

What I've come up with so far is this declaration:

declare module 'youtube-dl-exec' {
  type ExecaChildProcess = import('execa').ExecaChildProcess;

  const youtubeDl = (url: string, flags?: YtFlags, options?: Options<string>) => Promise<YtResponse>;
  youtubeDl.exec = (url: string, flags?: YtFlags, options?: Options<string>) => ExecaChildProcess;

  export default youtubeDl;
}

Now the existence and signature of exec is seen by Typescript, but with the return type of any. I don't think the type import is a problem, indeed even if I change the return type to a primitive string the Typescript compiler still sees the return type of exec as `any.

Since the assignment of the function property almost works, I feel like I'm on the right track, but can't figure out how to specify the return type of this function property.


Solution

  • This in implemented by either using namespace

      type ExecaChildProcess = import('execa').ExecaChildProcess;
    
      declare const youtubeDl: (url: string, flags?: YtFlags, options?: Options<string>) => Promise<YtResponse>;
      declare namespace youtubeDl {
        export const exec: (url: string, flags?: YtFlags, options?: Options<string>) => ExecaChildProcess;
      }
      export default youtubeDl;
    }
    

    or merging function type with object type

    declare module 'youtube-dl-exec' {
      type ExecaChildProcess = import('execa').ExecaChildProcess;
    
      declare const youtubeDl: (
        (url: string, flags?: YtFlags, options?: Options<string>) => Promise<YtResponse>
      ) & {
        exec: (url: string, flags?: YtFlags, options?: Options<string>) => ExecaChildProcess;
      }
    
      export default youtubeDl;
    }