Hay tipos con naturaleza autoaplanadora que se llama Idempotencia:
https://en.wikipedia.org/wiki/Idempotencia
La idempotencia es la propiedad de ciertas operaciones en matemáticas e informática por la que se pueden aplicar varias veces sin cambiar el resultado más allá de la aplicación inicial.
En JavaScript/TypeScript, tenemos el objeto Object/Number para instancias de idempotencia.
Un caso de uso del mundo real es escribir sus propias Promesas con el tipo adecuado en TypeScript. Nunca puede tener Promise<Promise<T>> solo Promise<T> ya que las promesas se aplanan automáticamente. Lo mismo puede ocurrir con las mónadas, por ejemplo.
console.log( Number(5) === Number(Number(5)) ); // trueDe manera concisa, a menudo se expresa como
TTX = TX
Editar: de hecho, este puede ser un concepto algo confuso; porque Idempotent nunca tiene una estructura más que T, en forma de matriz JS [foo] . Por otro lado, la operación de mónadas (enlace en palabra Haskel) es TTX = TX, pero tiene una estructura como [[foo]] .
La composición Array.map es [[foo]] => [[[foo]]]
Array.flatMap composición map+flat(TTX=TX) es [[foo]] => [[foo]]
esto es mónada, pero no idempotente, creo. Confuso, si.
De alguna manera me las arreglé para escribir en función
const toObject = <A, X>(x: A): A extends T<X> ? A : //... ((X:object)=> {/* ... */})(Object(x)) ; A extends T<X> ? A : //... funciona en el contexto del interior de algunas funciones, pero no sé cómo escribir el tipo solo, e incluso con la estructura de la función, es muy complicado y siento que algo está muy mal.
Lo que quiero saber y escribir es una definición del tipo idempotente en TypeScript
type T<X> = ??? //where T<T<X>> === T<X>Podrías escribir un envoltorio idempotente alrededor de algún tipo interno:
// just for reference, more practically this could be Promise<T> type InnerType<T> = [T]; type IdempotentWrapper<X> = X extends InnerType<unknown> ? X : InnerType<X>; type Foo = IdempotentWrapper<number>; // equivalent to InnerType<number> type Bar = IdempotentWrapper<IdempotentWrapper<number>>; // equivalent to InnerType<number> as well