Take a look at the code snippet below which utilizes phantom types:
const strlen = (str: string) => str.length;
type Const<A, B> = { type: 'Const', value: A };
const Const = <A, B = never>(value: A): Const<A, B> => ({ type: 'Const', value });
const map = <A, B, C>(_f: (value: B) => C, { value }: Const<A, B>): Const<A, C> => Const(value);
const contramap = <A, B, C>(_f: (value: C) => B, { value }: Const<A, B>): Const<A, C> => Const(value);
const constant = Const(true);
map(strlen, constant); // works
contramap(strlen, constant); // works
The program above successfully passes type checking due to the correct inference of types. The inferred type of the `constant` value is `Const
However, I attempted to rewrite the expressions using methods instead of functions for convenience:
const strlen = (str: string) => str.length;
interface Const<A, B> {
map: <C>(f: (value: B) => C) => Const<A, C>;
contramap: <C>(f: (value: C) => B) => Const<A, C>;
}
const Const = <A, B = never>(value: A): Const<A, B> => ({
map: () => Const(value),
contramap: () => Const(value)
});
const constant = Const(true);
constant.map(strlen); // works
constant.contramap(strlen); // error
As observed, the `map` method functions correctly, but the `contramap` method encounters an error. This discrepancy arises from the type of `constant` being `Const
Due to this limitation, either `map` or `contramap` can work individually, but not both. If the object's type is `Const
Is there a way to enable both `map` and `contramap` methods to function effectively instead of just one?