Skip to main content

refine(refiner): PartialLens

ts
refine = <A, B extends A>(refiner: (a: A) => B | false) => PartialLens<B, A>;
ts
refine = <A, B extends A>(refiner: (a: A) => B | false) => PartialLens<B, A>;

This combinator allows you to narrow the type focused by the optic it is passed to.
It returns a new partial optic focused on the original value in its narrowed type, or undefined if the narrowing failed.

The refiner function must return the original value in its narrowed type or false if it can't be narrowed to this type.

Examples:

- On the branch of a discriminated union

ts
import { refine } from "@optics/react/combinators";
 
type Result<T> =
| { type: "success"; value: T }
| { type: "failure"; errorMessage: string };
 
const resultOptic = createState<Result<number>>({ type: "success", value: 42 });
 
const successOptic = resultOptic.derive(
refine((res) => res.type === "success" && res)
);
 
successOptic.get(); // { type: 'success', value: 42 }
const successOptic: Optic<{ type: "success"; value: number; }, partial>
 
resultOptic.set({ type: "failure", errorMessage: "Catastrophic meltdown" });
 
successOptic.get(); // undefined
ts
import { refine } from "@optics/react/combinators";
 
type Result<T> =
| { type: "success"; value: T }
| { type: "failure"; errorMessage: string };
 
const resultOptic = createState<Result<number>>({ type: "success", value: 42 });
 
const successOptic = resultOptic.derive(
refine((res) => res.type === "success" && res)
);
 
successOptic.get(); // { type: 'success', value: 42 }
const successOptic: Optic<{ type: "success"; value: number; }, partial>
 
resultOptic.set({ type: "failure", errorMessage: "Catastrophic meltdown" });
 
successOptic.get(); // undefined

- On a built-in type

ts
import { refine } from "@optics/react/combinators";
 
const unknownValueOptic = createState<unknown>(42);
 
const numberOptic = unknownValueOptic.derive(
refine((x) => typeof x === "number" && x)
);
 
numberOptic.get(); // 42
const numberOptic: Optic<number, partial>
 
unknownValueOptic.set("Hello world");
 
numberOptic.get(); // undefined
ts
import { refine } from "@optics/react/combinators";
 
const unknownValueOptic = createState<unknown>(42);
 
const numberOptic = unknownValueOptic.derive(
refine((x) => typeof x === "number" && x)
);
 
numberOptic.get(); // 42
const numberOptic: Optic<number, partial>
 
unknownValueOptic.set("Hello world");
 
numberOptic.get(); // undefined

- On a user-defined type with a type-guard

ts
import { refine } from "@optics/react/combinators";
 
type User = {
userName: string;
};
 
function isUser(value: unknown): value is User {
return typeof (value as User).userName === "string";
}
 
const stateOptic = createState(untypedInitUser());
const stateOptic: Optic<any>
 
const myTypeOptic = stateOptic.derive(
refine((value) => isUser(value) && value)
);
 
myTypeOptic.get(); // { userName: 'John Doe' }
const myTypeOptic: Optic<User, partial>
ts
import { refine } from "@optics/react/combinators";
 
type User = {
userName: string;
};
 
function isUser(value: unknown): value is User {
return typeof (value as User).userName === "string";
}
 
const stateOptic = createState(untypedInitUser());
const stateOptic: Optic<any>
 
const myTypeOptic = stateOptic.derive(
refine((value) => isUser(value) && value)
);
 
myTypeOptic.get(); // { userName: 'John Doe' }
const myTypeOptic: Optic<User, partial>