You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
//this demonstrates the problem with using optics to modify union types (whether using poly or monomorphic optics)
typeManual1={URI: "Manual1";p1: boolean;players: number[];reinforcementsCount: number;};typeManual2={URI: "Manual2";p2: number;players: number[];reinforcementsCount: number;};typeOneOfTheStates=Manual1|Manual2;constopticsTest=(input: OneOfTheStates)=>{//first some basic discriminated union sanity checks://type "Manual1" | "Manual2" as expectedconsturi=input.URI;if(input.URI=="Manual1"){input.p1;//discriminated field only on Manual1 works here}//now a demo of the problem using the opticsconstreinforcementsCount_=optic_<OneOfTheStates>().prop("reinforcementsCount");constreinforcementsCount=optic<OneOfTheStates>().prop("reinforcementsCount");//NOTE: Uncomment any of these 3 to get ts error:// const val_: OneOfTheStates = set(reinforcementsCount_)(3)(input);// const val: OneOfTheStates = set(reinforcementsCount)(3)(input);// return modify(reinforcementsCount)(a => 5)(input);//CULPRIT: Non-Distributive Omit<T,K> used by library breaks discriminated unions//Since i am using optics modify, the type of modify gives me an `Omit<Type, "propertyModified"> & { propertyModified: ItsType }` //Omit here doesn't preserve the input type as a discriminated union; it creates a single type where URI is one or the other, and the shared properties are listed, //but it loses the properties unique to each disrciminated union member.//because the implementation of Omit, turns out, is not distributive over unions.typeX=Omit<OneOfTheStates,"reinforcementsCount">;constinputAsX=inputasX;if((inputAsX.URI=="Manual1")){//Uncomment to see unexpected TS ERROR!// inputAsX.p1; }//Since conditional types are distributive for unions (T is a union), we get a distribution of Omit<EachType, K> as a union result//preserving our ability to typecheck it:typeDistributiveOmit<T,KextendskeyofT>=Textendsany
? Omit<T,K>
: never;typeX2=DistributiveOmit<OneOfTheStates,"reinforcementsCount">;constinputAsX2=inputasX2;if(inputAsX2.URI=="Manual1"){inputAsX2.p1;//this works due to the solution of distributed omit}
SOLUTION: Use a distributive Omit in optics-ts
The text was updated successfully, but these errors were encountered:
import { optic, optic_ } from "optics-ts";
//this demonstrates the problem with using optics to modify union types (whether using poly or monomorphic optics)
SOLUTION: Use a distributive Omit in optics-ts
The text was updated successfully, but these errors were encountered: