Effect CommunityEC
Effect Community5mo ago
16 replies
mil2

Type narrowing in TypeScript can be tricky, especially when dealing with complex types like `Resu...

Does anyone know how to get type narrowing working on Atom Results? I have an atom that maps 404's to Option.none() and success to Option.some() As a result I was wanting NotFound to be removed from the return type. I've tried Result.match, Result.builder and explicit typing but I can't seem to remove it from the type

import { Atom, Result } from "@effect-atom/atom"  
import { Option } from "effect";

// Mock client query that returns Result<Profile, NotFound | ParseError>
type Profile = { user_id: string; name: string };
type ApiError = { _tag: "NotFound" | "ParseError" };
const mockGetUser = Atom.family((id: string) =>   
  Atom.make((): Result.Result<{ user_id: string; name: string }, { _tag: "NotFound" | "ParseError" }> => {  
    if (id === 'not-found') {  
      return Result.fail({ _tag: 'NotFound' as const });  
    }
    if (id === 'parse-error') {  
      return Result.fail({ _tag: 'ParseError' as const });  
    }
    return Result.success({ user_id: id, name: 'Test User' });  
  })  
);

const userAtomInferred = Atom.make((get) => {    
  const user_id = 'test_id';  
  const userResult = get(mockGetUser(user_id)).pipe(  
    Result.map(Option.some), // Transform Result<UserProfile, E> to Result<Option<UserProfile>, E>  
    (result) => Result.builder(result)  
      .onErrorTag('NotFound', () => Result.success(Option.none())) // Handles NotFound  
      .orElse(() => result) // Leave alone for success, initial, other errors
  );  
  return userResult;  
});
// const userResult: Result.Result<Option.Option<{
//     user_id: string;
//     name: string;
// }>, {
//     _tag: "NotFound" | "ParseError"; <--- Would expect "NotFound" to be excluded from type
// }> | Result.Success<Option.Option<never>, never>
Was this page helpful?