es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Tipo de retorno basado en argumento genérico opcional.

No puedo transferir los muchos ejemplos de sobrecarga de funciones en SO a mi caso de uso:

const createAccessor = <t>(defaultValue: T) => {

const value = defaultValue

function fetch(): T;
function fetch<tpart>(selector?: (obj: T) => TPart) {
    if (selector)
        return selector(value)

    return value
}

return { fetch }

}

const obj = createAccessor({
    part1: { a: 1, b : 2 },
    part2: { name: 'Hans' }
})

// De esta manera quiero usarlo:

const fullObject = obj.fetch()              // debería devolver T
const part1 = obj.fetch(o => o.part1)       // debería devolver TPart

(también en ts-playground

Eliminar la primera sobrecarga permite compilar, pero los tipos de retorno están equivocados. ¿Qué me estoy perdiendo?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema con la implementación actual es que la función fetch en realidad son dos funciones diferentes con implementaciones separadas, pero ambas se llaman fetch debido a la sobrecarga de funciones. Esto funciona bien en JavaScript, pero TypeScript requiere que especifiques el tipo de retorno de una función para determinar qué implementación de una función sobrecargada estás usando.

    En este caso, ambas funciones fetch tienen el mismo nombre y lista de parámetros, por lo que TypeScript no puede diferenciarlas y los tipos de retorno no se infieren correctamente.

    Para solucionar esto, puedes usar nombres diferentes para las dos implementaciones diferentes de fetch, de la siguiente manera:

    const createAccessor = <t,>() => {
        const value: T = {} as any; // Usa `{} as any` para permitir valores predeterminados de indefinido
    
        function fetch(): T;
        function fetch<tpart>(selector?: (obj: T) => TPart): TPart | T {
            if (selector) {
                return selector(value);
            }
            return value;
        }
    
        // Usa nombres de función diferentes para las dos implementaciones diferentes
        return { fetch, fetchPart: fetch };
    };
    
    const obj = createAccessor({
        part1: { a: 1, b: 2 },
        part2: { name: 'Hans' }
    });
    
    // Usa los nombres distintos de función para las dos implementaciones diferentes
    const fullObject = obj.fetch();
    const part1 = obj.fetchPart(o => o.part1);
    

    Ahora TypeScript puede determinar la implementación correcta de fetch basada en el nombre, y los tipos de retorno deberían inferirse correctamente.</t,>

Comments are closed.