Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add invariant #620

Open
cjquines opened this issue Apr 7, 2024 · 2 comments
Open

Add invariant #620

cjquines opened this issue Apr 7, 2024 · 2 comments
Labels
feature request New feature or request help wanted Extra attention is needed

Comments

@cjquines
Copy link
Collaborator

cjquines commented Apr 7, 2024

From #469 . Could also be named assert, throwIf, etc.

I think, for invariant to be most useful in data-last cases, it should have the type

function invariant<T, U extends T>(
    guard: (data: T) => data is U
): (data: T) => U;

so you can call it like

pipe(
  data as number | string,
  invariant(isNumber),
  data => data, // data has type number 
);

But, I think for invariant to be useful for data-first cases, the type would be quite different

function invariant<T, U extends T>(
    data: T,
    guard: (data: T) => data is U
): asserts data is U;

as in

(data: number | string) => {
  invariant(data, isNumber);
  data // data has type number
}

Note that in the data-last case, we return data unchanged; in the data-first case, we return void.

For non-guard cases, I don't think we can carry type-level information, so we could have an overload that takes a guard of (data: T) => boolean and doesn't narrow data.

See playground.

@cjquines cjquines added the feature request New feature or request label Apr 7, 2024
@eranhirsch
Copy link
Collaborator

I really want this! I've also been thinking about it recently. I think that tiny-invariant does some optimizations under-the-hood for production builds, which go beyond how we think about Remeda functions, and I don't want to suggest people stop using that library (and lose out on benefiting from those optimizations), but also don't want to just clone tiny-invariant inside Remeda as those kind of optimizations are what we usually consider; which brings me to think of having this as a utility that lives side-by-side with the regular invariant...

In one of my project's I ended up calling it "validate" (so it doesn't name clash with invariant) and used tiny-invariant in the implementation. This might mean adding tiny-invariant as a dependency, but that would be a first runtime dependency for remeda, could also be a peer dependency I guess...

TL;DR - 🤷🏼

@cjquines
Copy link
Collaborator Author

cjquines commented Apr 7, 2024

having it as a peer dep would be fine i think? we could attempt to import it, and if not use our own... but then i'd be concerned about how that works with bundling

@cjquines cjquines added the help wanted Extra attention is needed label Apr 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants