Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

prefer-array-literal: how can one specify the size of the array? #822

Closed
IllusionMH opened this issue Feb 14, 2019 · 7 comments · Fixed by #862
Closed

prefer-array-literal: how can one specify the size of the array? #822

IllusionMH opened this issue Feb 14, 2019 · 7 comments · Fixed by #862
Labels
Requires Type Checker Must be implemented with a "typed" rule that uses a TypeScript program. Status: Accepting PRs Type: Rule Feature Adding a feature to an existing rule.
Milestone

Comments

@IllusionMH
Copy link
Contributor

how can one specify the size of the array?

const foo = new Array(10)
?

Originally posted by @ogiexela in #110 (comment)

@IllusionMH
Copy link
Contributor Author

@ogiexela it depends on case what you want to achieve.

Using new Array rarely have any advantages (e.g. it won't create optimized arrays thread), however behaves differently if there is one or more arguments that leads to errors. Therefore this rule was created.

In general case it is better to use [] and fill it with values later (see thread).

If you really need to create array in this way you can disable error for this line with rule flags e.g. // tslint:disable-next-line:prefer-array-literal on previos line.

@ogiexela
Copy link

What about the case where I already know the exact size that I need the array to be.
Then according to this per-defined size array performs better.
Or am I missing something?

https://jsperf.com/push-method-vs-setting-via-key/23

image

@IllusionMH
Copy link
Contributor Author

It will depend on your use cases. As mentioned in this tweet you see that new Array will be faster to create array and fill it with index access.

If your application creates new big arrays really often and usually uses regular for loop to iterate though this array - new Arraly(length) most likely will be better fo performance.
And you should use // tslint:disable-next-line:prefer-array-literal because you are sure that you are passing 1 element and expect to have array of passed length.

However if big arrays are created only once (or in rare ocassions) and app heavily relies on freqest uses of .map, .forEach etc. - those loops mig be slower that in case when you use .push to keep array packed.

Anyway - if performance is your concern you should check which of these both approaches will be faster in your case.


Main reason for this rule - avoid different/unexpected behavior between cases new Array(1000), new Array(1000, 2000), and new Array('1000'). And new Array(length) has its pros and cons for performance in different cases.

If you need reallocate array - better to disable rule for that single line (only option available ATM).


If I understand correctly - similar rule in ESLint (and migrated rule for TS) allows Array constructors with 1 argument. May be makes sense to add flag that will allow this use cases?

@JoshuaKGoldberg what do you think?

@JoshuaKGoldberg
Copy link

JoshuaKGoldberg commented Feb 23, 2019

Sure, seems reasonable to add a flag to allow just the case of the constructor with 1 argument. The flag should allow arrays to be created with new only when there is a single argument of type number.

A few thoughts:

  • This requires the type checker, for the case of variables being used instead of literals. The rule should therefore become an optionally typed rule that requires the type checker if this option is enabled.

  • Types that can include non-number types, such as union types and generic types not bound to extend a numeric type, should not be allowed:

    // Accidentally creates array of size (item) if TItem is numeric
    function createArrayOfSizeOne<TItem>(item: TItem) {
        return new Array(item);
    }

@JoshuaKGoldberg JoshuaKGoldberg added Requires Type Checker Must be implemented with a "typed" rule that uses a TypeScript program. Status: Accepting PRs Type: Rule Feature Adding a feature to an existing rule. and removed Type: Question labels Feb 23, 2019
IllusionMH added a commit to IllusionMH/tslint-microsoft-contrib that referenced this issue May 14, 2019
IllusionMH added a commit to IllusionMH/tslint-microsoft-contrib that referenced this issue May 14, 2019
IllusionMH added a commit to IllusionMH/tslint-microsoft-contrib that referenced this issue May 17, 2019
IllusionMH added a commit that referenced this issue May 17, 2019
* Use only tslint --test for prefer-array-literal rule

* Restrict only global objects with Array (fixes #856)

* Add allow-single-argument option and check argument types (fixes #822)

* Update docs and metadata for prefer-array-literal rule

* Apply suggestions related to wording in README.md

Co-Authored-By: Josh Goldberg <joshuakgoldberg@outlook.com>

* Change new option name to allow-size-argument

* Use Set for restricted namespaces. Add `self` to restrictions

* Fix error message for incorrect size argument

* Handle array spread in argument position

* Drop node text from all error messages

* Handle potential exceptions from TS

* Add comment about additional check for SpreadElement
@IllusionMH IllusionMH added this to the 6.2.0-beta milestone May 18, 2019
@IllusionMH
Copy link
Contributor Author

6.2.0-beta was published to npm that allows this behavior.
You can install latest version with npm install tslint-microsoft-contrib@beta and list restriction for invocations with single argument with "prefer-array-literal": [true, {"allow-size-argument": true}] in your tslint.json

@astorije
Copy link
Contributor

@IllusionMH, @JoshuaKGoldberg, would you be open to default this parameter to true? It seems like a reasonable thing to allow by default.

@JoshuaKGoldberg
Copy link

@astorije I think so, yeah. Agreed it's reasonable. #678

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Requires Type Checker Must be implemented with a "typed" rule that uses a TypeScript program. Status: Accepting PRs Type: Rule Feature Adding a feature to an existing rule.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants