Así que creé una función de combinación que toma un objeto y una clave de otro objeto de objetos. La función luego devuelve los objetos combinados como se muestra a continuación.
const data = { end: 'World' } const working = { test: 'Worked' } const map = { data, working } export type Map = typeof map; export type Keys = keyof Map; function merge<A, B extends Keys, C extends Map[B] & A>(input: { obj: A; append?: B; }) { const append = input.append ? map[input.append] : {}; return { ...input.obj, ...append } as C } Ahora esto funciona perfectamente bien cuando el objeto del map tiene> 1 propiedad. alias
const initial = { start: 'Hello' } const a = merge({ obj: initial, append: 'data' ); const b = merge({ obj: initial }); // Available as expected console.log(a.end); // Errors as expected console.log(b.end); Sin embargo, si cambio el objeto del map para que solo tenga 1 propiedad así
const map = { data }Entonces esto ocurre
const a = merge({ obj: initial, append: 'data' ); const b = merge({ obj: initial }); // Available as expected console.log(a.end); // Available but outputs undefined console.log(b.end); Entiendo lo que está pasando. Cuando el objeto del map solo tiene 1 propiedad, el genérico está predeterminado en esa clave, por lo que TypeScript cree que el objeto está fusionado cuando no lo está.
¿Cómo evito esto?
export type Map = typeof map; export type Keys = keyof Map; function merge<A, B extends C extends keyof Map ? A & Map[C] : A, C extends undefined | keyof Map = undefined>(input: { obj: A; append?: C; }) { const append = input.append ? map[input.append as keyof Map] : {}; return { ...input.obj, ...append } as B } const data = { end: 'World' } const map = { data } // Testing const start = { hello: 'World' } const a = merge({ obj: start }); // Outputs as expected console.log(`${a.hello} World`); // Errors as expected console.log(`${a.hello} ${a.end}`); const b = merge({ obj: start, append: 'data' }) // Outputs as expected console.log(`${b.hello} ${b.end}`);Así es como lo he hecho funcionar.
Básicamente C se extiende undefined | keyof Map y tiene un tipo predeterminado de undefined , por lo que, de forma predeterminada, el tipo devuelto es A & undefined . Cuando un valor que debe ser keyof Map se pasa como el anexo, entonces C se convierte en ese tipo y, por lo tanto, el tipo devuelto es Map[C] & A