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

Ideas #1

Closed
9 tasks done
sindresorhus opened this issue Sep 21, 2017 · 35 comments
Closed
9 tasks done

Ideas #1

sindresorhus opened this issue Sep 21, 2017 · 35 comments

Comments

@sindresorhus
Copy link
Owner

sindresorhus commented Sep 21, 2017

I'm gonna try hard not to go overboard with stuff I will never need, but just a quick brain dump:

  • .withinRange(3, [0, 5])
  • .generator()
  • .domElement()
  • .generatorFunction()
  • .infinity() (Would match Infinity and -Infinity) (Maybe .infinite() would be a better name?)
  • .empty([]) (string, array, object, map, set, ...)
  • .blob()
  • .asyncFunction()
  • And .any()/.all() methods to match multiple types.

Feedback wanted! 😀

@glhrmv
Copy link

glhrmv commented Sep 22, 2017

How are you thinking .withinRange should work? Is something like this OK?

is.withinRange = (x, arr) => (x > Math.min.apply(Math, arr)) && (x < Math.max.apply(Math, arr));

@sindresorhus
Copy link
Owner Author

@glhrmv I was thinking:

is.withinRange = (input, [lower, upper]) => input >= lower && input <= upper;

@glhrmv
Copy link

glhrmv commented Sep 22, 2017

Array destructuring is definitely more elegant, I forgot that was a thing.

As for .domElement, that'll require following this procedure for testing, right? If so, I can get on that as well.

@sindresorhus
Copy link
Owner Author

As for .domElement, that'll require following this procedure for testing, right?

Yup. Let’s do it in a separate test file.

@glhrmv
Copy link

glhrmv commented Sep 23, 2017

I couldn't make browser-env (or even window) make document defined in the test file, for some reason. In any case, the idea I had of is.domElement(x) was to make sure x is an instanceof Element, but obviously Node doesn't support Element, either.

I'm giving this up to anyone who wants to deal with it, and I'm interested to see how this type of issue is solved.

@sindresorhus
Copy link
Owner Author

@yeskunall
Copy link
Contributor

With #4:

  • .generator()
  • .generatorFunction()

@nrebhun
Copy link

nrebhun commented Oct 4, 2017

Hey @sindresorhus, Hacktoberfest is upon us! 😜

How about getting some more eyes on this issue/repo with the relevant tag?

@fega
Copy link

fega commented Oct 4, 2017

what about include it in AVA t.is ?

@gioragutt
Copy link
Collaborator

@fega wouldn't that create some weird circular dependency?

@kodie kodie mentioned this issue Oct 5, 2017
@noamokman
Copy link

@gioragutt nope, you would just install the latest version at the ava project

Unrelated, what about:

const a = 5;
const b = {};
const c = 'asd';
is.string(a,b,c); // false

@gioragutt
Copy link
Collaborator

@noamokman what is the case you're checking here exactly?

this returns false because the method only relates to arguments[0], which is a, so is.string(5) === false makes sense.

what do you expect this to return?

@gioragutt
Copy link
Collaborator

gioragutt commented Oct 5, 2017

@sindresorhus

  • Observable
  • Promise
  • Subject (related to Observable)

@noamokman
Copy link

@noamokman what is the case you're checking here exactly?

this returns false because the method only relates to arguments[0], which is a, so is.string(5) === false makes sense.

what do you expect this to return?

I mean that if multiple values are passed is should test all values

@gioragutt
Copy link
Collaborator

@noamokman perheps we can implement that into is.any or is.all, where they would like:

is.all = (pred, ...values) => {
  if (!is.array(values) || is.empty(values)) {
    return false;
  }

  const hits = values.find(pred);
  return hits.length === values.length;
};

and is.any will check hits.length > 0.
or something of that sort.

@sindresorhus
Copy link
Owner Author

I mean that if multiple values are passed is should test all values

No, that's should be a separate method.

@sindresorhus
Copy link
Owner Author

@gioragutt

Observable

👍 See how to do it here: https://github.com/sindresorhus/is-observable/blob/master/index.js

Promise

Already included.

Subject (related to Observable)

What is this and why do you need to detect it? Can you link to some reading material?

@gioragutt
Copy link
Collaborator

gioragutt commented Oct 5, 2017

@sindresorhus Subjects are extended from Observables. They are basically Observables you can call next on, and invoke observers

@melvin0008
Copy link
Contributor

@sindresorhus @gioragutt

Could I get more insight into what is expected from .any and .all ?

is.any(value, [types] ) ?
is.any(5,[string, Number]) ?

Is it similar for .all?
Is this what you have in mind?

@gioragutt
Copy link
Collaborator

@melvin0008 I guess this is up for discussion, because as you stated, there are many ways to interpret any and all.

@sindresorhus your thoughts?

@gioragutt
Copy link
Collaborator

is.falsy > value => !value ?
could be used in other methods as well, f.e in #16

@sindresorhus
Copy link
Owner Author

Regarding, any and all.

Returns true if any of the input values returns true in the predicate:

any(predicate, values…)

Returns true if all of the input values returns true in the predicate:

all(predicate, values…)

Example:

any(is.string, {}, true, '🦄');
//=> true

@sindresorhus
Copy link
Owner Author

is.falsy > value => !value ?

👍 And truthy. I like it because it makes the intent more clear. Often people misuse !foo when they actually don't want falsy.

@brandon93s
Copy link
Collaborator

brandon93s commented Oct 15, 2017

Others for consideration:

  • .arrowFunction()
  • .numeric() - returns true for numbers and numeric strings (e.g. '4.3')
  • .arraylike() - true for things like arguments and results of document.getElementsByTagName('p'). They have a .length property and index accessing but no array methods (pop, push, etc.).
  • .decimal()
  • .even()
  • .odd()
  • .greaterThan(4, 3) or .gt(4, 3) and equal to equivalent .gte(4, 3)
  • .lessThan(3, 4) or .lt(3, 4) and equal to equivalent .lte(3, 4)
  • .truthy() - is.truthy = x => !!x;
  • .falsy()
  • .emptyOrSpaces() - returns true for .empty() or whitespace strings (e.g. ' '). Alternatively, just adjust the behavior of .empty()
  • .arguments() - specifically checks for arguments
  • .positive()
  • .negative()
  • .safeInteger() - Here is some reading
  • .nil() - true for is.null(x) || is.undefined(x) - often checked together
  • .char() - true for an ASCII character?
  • .emoji() - true for emoji

Update: Added a few more... total brain dump. Glad to implement any of these pending need / usefulness.

@brandon93s
Copy link
Collaborator

brandon93s commented Oct 16, 2017

inRange could be enhanced to support:

Dates

is.inRange(new Date('March 1, 2017'), [new Date('January 1, 2017'), new Date('July 1, 2017')])
// => true

date.getTime() >= min && date.getTime() <= max

Questions:

  • What would the lower bound default to? Epoch?

Text - Alphabetical

is.inRange('Brandon', ['Andrew', 'Cole'])
// => true

name >= min && name <= max

Questions:

  • What would the lower bound default to?
  • Is there a use case for this?

@sindresorhus
Copy link
Owner Author

.arrowFunction()

Use-case?

.numeric()

I don't like the looseness of this. We should not mix types like that. We could have numericString().

.arraylike()

👍

.decimal()

I considered this when doing .integer, but I couldn't come up with a use-case. It makes sense to have .integer because some methods might accept just whole numbers, but only accepting decimals doesn't make sense, a whole number like 3 is still a valid decimal.

.even()
.odd()

👍

.greaterThan(4, 3)

We already have min and max which overlaps with gte(), but it might be worth it still, for readability reasons. (@gioragutt Thoughts?) gte is not a good name though, even though it's verbose, I would go with, greaterThanOrEqual().

.truthy() - is.truthy = x => !!x;
.falsey()

👍 , but: falsey => falsy

.emptyOrSpaces()

👍

is.inRange(new Date('March 1, 2017'), [new Date('January 1, 2017'), new Date('July 1, 2017')])
// => true

I would make a new method for this: dateInRange([date], range)

date would be optional and default to new Date(). The range would not have an optional lower bound as it doesn't make sense here.

Text - Alphabetical
is.inRange('Brandon', ['Andrew', 'Cole'])

👎 I don't see the point in supporting a range for this.

@gioragutt
Copy link
Collaborator

gioragutt commented Oct 16, 2017

@sindresorhus

.emptyOrSpaces()

I'd prefer .emptyOrWhitespaces, usually this is the use case

.lt/gt/lte/gte

I honestly think that doing this would reduce code readability.
I guess this can be useful when you want to provide a comparer to a method, though.
This can make it a bit better.
The question is - is the use case of using the methods over just using the operator worth adding 4 methods to the API.

If we wish to keep the API cleaner, this might not be a good idea to do those methods. But if you believe this wouldn't create much of a bloat, then I'm fine with it.

dateInRange([date], range)

Do you mean that range would be an upper bound only? I think that it's kinda counter intuitive to say that date is in range, when range is actually just a max-value.

And there are definitely use cases for checking against a lower bound.

Text - Alphabetical

I agree with you on that there's no point in a range (this is basically .includes),

But this does give 2 new ideas:

  • Alphabetic - check is string is purely alphabetic ([a-z]. [A-Z], and whitespaces)
  • Alphanumeric - checking if a string is alphanumeric ([a-z]. [A-Z], [0-9] and whitespaces. Although if we look for it, the spec for what's an A/N string might have something more than what I specified).

and this in turn makes sense to include numeric, or as you've suggested numericString.

@sindresorhus
Copy link
Owner Author

I'd prefer .emptyOrWhitespaces, usually this is the use case

Agreed, but should be .emptyOrWhitespace (without the s).

If we wish to keep the API cleaner, this might not be a good idea to do those methods. But if you believe this wouldn't create much of a bloat, then I'm fine with it.

I'm -0. Maybe if someone can convince me it has benefits of including it over just using the operators.

Do you mean that range would be an upper bound only? I think that it's kinda counter intuitive to say that date is in range, when range is actually just a max-value.

No, range would be an array with lower and upper bound.

Alphabetic - check is string is purely alphabetic ([a-z]. [A-Z], and whitespaces)

Use-case?

Alphanumeric - checking if a string is alphanumeric ([a-z]. [A-Z], [0-9] and whitespaces. Although if we look for it, the spec for what's an A/N string might have something more than what I specified).

Use-case?

@sindresorhus
Copy link
Owner Author

.arguments() - specifically checks for arguments

👎 No one should be using the arguments object now that we have rest/spread.

.positive()
.negative()

I guess this is the same case as gt and gte. Convince us.

.safeInteger() - Here is some reading

👍 Since we already alias some other useful native methods.

.nil() - true for is.null(x) || is.undefined(x) - often checked together

This is already included as nullOrUndefined. I considered nil, but it's not clear enough.

.char() - true for an ASCII character?

Not clear enough name. And, use-case?

.emoji() - true for emoji

Use-case?

@sindresorhus
Copy link
Owner Author

@brandon93s Awesome braindump! :)

@brandon93s
Copy link
Collaborator

brandon93s commented Oct 16, 2017

Appreciate the feedback!

.arrowFunction() - Since you cannot bind or call an arrow function, one could imagine a use case where a library needs to detect that an arrow function has been provided and throw an error to the consumer. Probably unnecessary until encountered, though.

.gt .lt .positive .negative etc - I'm in agreement on these ones. The operators themselves are more concise than having methods. No need for them.

.decimal .char .emoji - No immediate use cases come to mind.

@yeskunall
Copy link
Contributor

yeskunall commented Oct 16, 2017

is.emoji for when you don't want emojis in certain places. Legacy databases (MySQL with UTF-8 encoding) don't handle emojis well, so in that case, this addition might come in handy.

I've had to work on a project where emojis in the username were disallowed altogether. That's another use-case.

@sindresorhus
Copy link
Owner Author

.arrowFunction() - Since you cannot bind or call an arrow function, one could imagine a use case where a library needs to detect that an arrow function has been provided and throw an error to the consumer. Probably unnecessary until encountered, though.

That's a good use-case. I'm 👍 on this now.

@sindresorhus
Copy link
Owner Author

Legacy databases (MySQL with UTF-8 encoding) don't handle emojis well, so in that case, this addition might come in handy.

We won't add anything for legacy reasons.

I've had to work on a project where emojis in the username were disallowed altogether. That's another use-case.

This is a good use-case though. I'm 👍 on this.

@sindresorhus
Copy link
Owner Author

Most of this should be implemented now. Let's open new issues for additional requests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants