Patrones
¿Cómo acepto una clave de búsqueda rechazando tanto una consulta vacía como una con varias claves?
Construye una variante por clave: exige esa clave y prohíbe las demás con `never` opcional.
La receta
type ExactlyOne<T> = { [K in keyof T]: Required<Pick<T, K>> & Partial<Record<Exclude<keyof T, K>, never>> }[keyof T] type Search = ExactlyOne<{ id: string email: string handle: string }>
La compilación compila esto y comprueba cada resultado de abajo.
Cómo funciona
- 01
Required<Pick<T, K>>
La variante actual exige su clave seleccionada.
- 02
Partial<Record<Exclude<keyof T, K>, never>>
Cada clave no seleccionada es opcional, pero está prohibida si aparece.
Lo que obtienes
{ id: string } extends Search ? true : false→true{} extends Search ? true : false→false{ id: string; email: string } extends Search ? true : false→false
Dónde falla
Como `AtLeastOne`, crea un miembro de unión por clave. Mantén pequeño el objeto de origen o crecerán rápido los diagnósticos y el trabajo del editor.
Conclusión
Exige la clave elegida, prohíbe el resto e indexa la tabla mapeada para formar la unión.
