Closed anthonyjoeseph closed 3 years ago
@anthonyjoeseph, I really like this idea, however I'm wondering if we rearrange the type parameters, it might make it even easier to use (i.e. you don't have to supply a type parameter):
const makeRefinement = <TagName extends string>(
tag: TagName
) => <Tag extends string>(
tags: readonly Tag[]
) => <ADT extends { [t in TagName]: string }>(
s: ADT
): s is Extract<ADT, { [t in TagName]: Tag }> =>
tags.includes(s[tag])
const refinement = makeRefinement('_type')
declare const myXor: Xor<number, string>;
if (refinement(['left', 'right'])(myXor)) { // no type params
myXor._type // _type: "left" | "right"
myXor.value // value: string | number
}
what do you think?
I love it! I added another feature that causes a type error if any of the refinement tags are misspelled - it's a bit messy, but (I think) it works
It looks great as it is, though, if you'd rather just keep it simple
(edit: cleaned up to use more explicit non-naked type) (edit 2: here's one with better naming conventions)
Would you mind if I made a PR for this?
@anthonyjoeseph , No, go right ahead
This idea is for something like morphic-ts predicates
Not sure if this is desired or out of scope, but it might be handy! A possible use case could be in conjunction w/ fp-ts-routing -
makeRefinement
could refine groups of routesSpec:
Implementation: