Patrones
¿Cómo convierto `{ a: string } & { b: number }` en `{ a: string; b: number }` para que los tooltips se lean y las comprobaciones de igualdad pasen?
Un mapeo homomórfico recorre cada clave una vez y reconstruye un único objeto. Los modificadores sobreviven; la intersección no.
La receta
type Prettify<T> = { [K in keyof T]: T[K] } type Base = { a: string } type Extra = { b?: number; readonly c: boolean } type Merged = Prettify<Base & Extra>
La compilación compila esto y comprueba cada resultado de abajo.
Cómo funciona
- 01
type Prettify<T> = { [K in keyof T]: T[K] }
Parece que no hace nada, y para un objeto llano así es. Ante una intersección recorre la unión de ambos conjuntos de claves y emite un objeto con todas.
Lo que obtienes
Merged
→{ a: string; b?: number | undefined; readonly c: boolean; }Prettify<{ a: 1 } & { b: 2 }>→{ a: 1; b: 2; }Un objeto donde había dos. Nada cambió en la asignabilidad — solo la forma, que es lo que compara `Equal`.
Prettify<{ a: 1 }> extends { a: 1 } ? true : false→true
Dónde falla
Aplana un nivel. Una intersección anidada dentro de una propiedad sigue siendo intersección, y aplicarlo recursivamente expandirá también cada tipo integrado que toque — incluidos `Date` y `Promise`, que rara vez es lo que se quería.
Conclusión
Las intersecciones ensamblan un tipo de objeto; un mapeo homomórfico lo remata. Ensamblar sin rematar es la razón más común de que un tipo con buen aspecto falle una comprobación de igualdad.