Búsqueda de sitios web

node.js - ¿Por qué TypeScript no puede inferir este tipo?


Estoy tratando de tener una versión tipada de promisify, un método que convierte funciones con callbacks de Node en promesas nativas para poder usarlas con await async.

Una de las firmas de tipo es la siguiente:

function promisify<A1, A2, R1>(
nodeFunction: (
      arg1: A1, 
      arg2: A2, 
      callback: (err: any, r1: R1) => any
      ) => any, 
arg1 : A1, 
arg2 : A2): Promise<R1> 

Esto es para una función de Node que toma dos argumentos y devuelve un único valor en el callback, por ejemplo, fs.readFile, ten en cuenta que dado que readFile tiene múltiples firmas de llamada, la función pide esos argumentos para que podamos inferir A1 y A2

Los genéricos explícitos funcionan, pero el compilador no puede inferir los tipos, el mensaje del compilador es:

The type argument for type parameter 'A2' cannot be inferred from the usage.
Consider specifying the type arguments explicitly.
Type argument candidate '(err: ErrnoException, data: Buffer) => void' 
is not a valid type argument because it is not a supertype of candidate 'string'.

La firma de readfile:

readFile(filename: string, encoding: string, 
         callback: (err: NodeJS.ErrnoException, data: string) => void): void;

Es la única sobrecarga que acepta una cadena en el segundo argumento, si pasamos dos cadenas en la llamada a la función:

promisify(fs.readFile, 'file.txt', 'utf8')

¿Por qué el compilador ha elegido la sobrecarga que acepta un objeto en lugar de una cadena en el segundo parámetro?

Dado que arg2 seguramente es una cadena ('utf8'), el compilador debería saber que A2 es una cadena y luego seleccionar únicamente la sobrecarga que acepta un string como segundo parámetro.

Estas son todas las firmas:

export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;
export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;