There are types with self flattening nature that is called Idempotence:
https://en.wikipedia.org/wiki/Idempotence
Idempotence is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application.
In JavaScript/TypeScript, we have Object/Number object for instance of idempotence.
A real world use-case is to write your own Promises with proper type in TypeScript. You can never have Promise<Promise<T>>
only ever Promise<T>
since promises auto-flatten. The same can happen with monads, for example.
console.log(
Number(5) === Number(Number(5))
); // true
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
In a concise way, it's often expressed like
TTX = TX
I somehow managed to write in function
const toObject = <A, X>(x: A): A extends T<X> ? A : //...
((X:object)=> {/* ... */})(Object(x)) ;
A extends T<X> ? A : //...
works in the context of inside of some functions, but I don't know how to write the type itself alone, and even with function structure, it's very complicated, and I feel something is very wrong.
What I want to know and write is a definition of the idempotent type in TypeScript
type T<X> = ???
//where
T<T<X>> === T<X>
CodePudding user response:
You could write an idempotent wrapper around some inner type:
// 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