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
New rule: prefer-readonly-type-declaration #259
New rule: prefer-readonly-type-declaration #259
Conversation
fd0d84e
to
73630ca
Compare
73630ca
to
ada5ed8
Compare
@jonaskello I think this implementation addresses all the issues and is pretty much ready to go. I copied over the upstream utils that we are waiting on for now. It can easily be stripped out later. There are a few changes I want to make to those utils but I'll submit upstream PRs to try and address those. Let me know what you think. |
30e515c
to
d58f518
Compare
de8af81
to
ab69810
Compare
302eb7d
to
57f17bd
Compare
ab69810
to
f3f9a65
Compare
Regarding the name of the rule, I'm thinking maybe Regarding the new |
If I understand correctly this rule will no longer check readonly declarations of function parameters but instead rely on the |
Rule nameI think having the word Aliases optionThis option is more powerful than the It's probably also worth noting that this new rule is now more strict than the previous one. Type aliases/interfaces are also checked as whole now, rather than the individual elements being individually checked. (The individual elements are also check but only for the purpose of the fixer - this is simply because implementing a fixer for the whole type would be more difficult and we already had the code to do it this way. I may implement the other way in the future.) I could maybe replace the {
"readonlyAliasPatterns": "^(?!I?Mutable).+$",
"mutableAliasPatterns": "^I?Mutable.+$",
"blacklistedAliasPatterns": "^Mutable$",
} Function parameters
That's actually not correct. This rule will still check function parameters just like before if they use a type literal (as opposed to a type reference). For example: // Will fail to both "prefer-readonly-type-declaration" and "@typescript-eslint/prefer-readonly-parameter-types"
function foo(param: { bar: number }) {} // Will fail to "prefer-readonly-type-declaration"
type Param = { bar: number };
// Will fail only to "@typescript-eslint/prefer-readonly-parameter-types"
function foo(param: Param) {} The main reason I kept this behavior was so that we can still implement our fixer (to add |
Yes, it is definitely a tradeoff between brevity and clarity. I have no strong opinion on this so let's go with the longer name.
I will have to think about this a little more but just a quick question on terminology for now. If we write eg.
Ah, I did not catch that, thanks for clarifying. Good point about the fixer, don't want to be without that :-). |
Things like |
Oh, I should point out that the this new rule also supports |
Yes, type MutableTuple = [string, number] // This is is ignored using `alias` option?
type MyTuple = [string, number] // This is flagged or if it is more geared towards something like this: type MutableObj = { x: number, y: {z: string} }; // This is is ignored using `alias` option?
type MyObj = { x: number, y: string }; // This is flagged or the intent is to support both these cases? |
To support both. |
Just to clairfy a bit about the let x = 15
x <- 15 // this will not work
let mutable y = 10
y <- 15 // this will work since y is marked as mutable The equivalent in js/ts is let x = 15 // this will not work becuase of prefer-const rule
let mutableY = 10 // this will work since y is named as mutable and is ignored by prefer-const rule The second escape hatch these languages provide is using the same modifier but on fields within a record type. The F# example link as above contians this example: type studentData =
{ ID : int;
mutable IsRegistered : bool;
mutable RegisteredText : string; } In this case type studentData =
{ readonly ID : number;
MutableIsRegistered : boolean;
MutableRegisteredText : string; } AFAIK the functional languages the rule is trying to emulate does not have an escape hatch that allows a whole type to be marked as mutable. You can of course mark every field with the modifier, and the equivalent in typescript with the rule would then be to prefix all field names with mutable. My concern is that I'm not sure it's a good idea to provide escape hatches for our rules that do not exist in functional-first languages. |
OTOH, typescript is really different from F#/ocaml/reasonml etc. so it might make sense to have more escape options :-). I guess the aliases option that enable whole type mutability would be like having the mutable modifier on the type keyword in F# etc. Something like this: type mutable studentData =
{ ID : int;
IsRegistered : bool;
RegisteredText : string; } I don't think this syntax exists in F# or other ML based languages but if it did I guess it would make all fields of the type |
I'm trying to think of use-cases for the // This works already with prefer-readonly-type and ignorePattern set to "^[mM]utable"
export const mutableNumbersArray: number[] = [1, 2, 3];
export type Foo = { mutableBar: number };
export type MutableNumbersArray = number[];
export const numbersArray: MutableNumbersArray = [1, 2, 3];
// This does not work with ignorePattern
export type MutableFoo = { bar: number }; So the case I have found so far is to mark a whole object type alias as mutable. Are there more cases? |
Fully functional programming languages such as Haskell don't even have the concept of mutability. Although F# allows for allowing for mutability, this is just an escape hatch into non-functional programming. I agree that we should try to support the same style of marking properties as mutable that F# does (via a naming convention); but we shouldn't simply lock into this being the end all. And yeah, as TypeScript is a very different language to F# and the like, enabling a way to mark an entire type as mutable seems like it should be supported - especially when working with 3rd-party libraries. In fact, our code is relying on this to work with ESLint see type MutableRuleTesterTests in this commit |
I just reworked the Now instead of the |
Also note that with the default config and // { "ignorePattern": "^[mM]utable" }
type Foo = { mutableBar: number };
// ^^^ Error - name suggests the type should not be mutable. To fix this the type's name would have to be renamed: // { "ignorePattern": "^[mM]utable" }
type MutableFoo = { mutableBar: number };
// ^^^^^^^^^^ No error but the mutable prefix has no effect. Or the // { "ignorePattern": "^[mM]utable", readonlyAliasPatterns: [] }
type Foo = { mutableBar: number }; // Works just like it did with `prefer-readonly-type`. |
Bumps [eslint-import-resolver-typescript](https://github.com/alexgorbatchev/eslint-import-resolver-typescript) from 2.5.0 to 2.7.1. - [Release notes](https://github.com/alexgorbatchev/eslint-import-resolver-typescript/releases) - [Changelog](https://github.com/alexgorbatchev/eslint-import-resolver-typescript/blob/master/CHANGELOG.md) - [Commits](import-js/eslint-import-resolver-typescript@v2.5.0...v2.7.1) --- updated-dependencies: - dependency-name: eslint-import-resolver-typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [eslint](https://github.com/eslint/eslint) from 8.8.0 to 8.14.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](eslint/eslint@v8.8.0...v8.14.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/stale](https://github.com/actions/stale) from 4 to 5. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](actions/stale@v4...v5) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [tslib](https://github.com/Microsoft/tslib) from 2.3.1 to 2.4.0. - [Release notes](https://github.com/Microsoft/tslib/releases) - [Commits](microsoft/tslib@2.3.1...2.4.0) --- updated-dependencies: - dependency-name: tslib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 2.1.0 to 3.1.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md) - [Commits](codecov/codecov-action@v2.1.0...v3.1.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 4.2.0 to 4.4.0. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/master/CHANGELOG.md) - [Commits](amannn/action-semantic-pull-request@v4.2.0...v4.4.0) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [fkirc/skip-duplicate-actions](https://github.com/fkirc/skip-duplicate-actions) from 3.4.1 to 4.0.0. - [Release notes](https://github.com/fkirc/skip-duplicate-actions/releases) - [Commits](fkirc/skip-duplicate-actions@v3.4.1...v4.0.0) --- updated-dependencies: - dependency-name: fkirc/skip-duplicate-actions dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [eslint-plugin-eslint-plugin](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/releases) - [Changelog](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/main/CHANGELOG.md) - [Commits](eslint-community/eslint-plugin-eslint-plugin@v4.1.0...v4.2.0) --- updated-dependencies: - dependency-name: eslint-plugin-eslint-plugin dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [ts-node](https://github.com/TypeStrong/ts-node) from 10.4.0 to 10.8.0. - [Release notes](https://github.com/TypeStrong/ts-node/releases) - [Commits](TypeStrong/ts-node@v10.4.0...v10.8.0) --- updated-dependencies: - dependency-name: ts-node dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli) from 0.31.0 to 0.31.1. - [Release notes](https://github.com/igorshubovych/markdownlint-cli/releases) - [Commits](igorshubovych/markdownlint-cli@v0.31.0...v0.31.1) --- updated-dependencies: - dependency-name: markdownlint-cli dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@semantic-release/npm](https://github.com/semantic-release/npm) from 9.0.0 to 9.0.1. - [Release notes](https://github.com/semantic-release/npm/releases) - [Commits](semantic-release/npm@v9.0.0...v9.0.1) --- updated-dependencies: - dependency-name: "@semantic-release/npm" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [rollup](https://github.com/rollup/rollup) from 2.68.0 to 2.75.5. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](rollup/rollup@v2.68.0...v2.75.5) --- updated-dependencies: - dependency-name: rollup dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 4.4.0 to 4.5.0. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md) - [Commits](amannn/action-semantic-pull-request@v4.4.0...v4.5.0) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [pascalgn/automerge-action](https://github.com/pascalgn/automerge-action) from 0.15.2 to 0.15.3. - [Release notes](https://github.com/pascalgn/automerge-action/releases) - [Commits](pascalgn/automerge-action@v0.15.2...v0.15.3) --- updated-dependencies: - dependency-name: pascalgn/automerge-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/HEAD/packages/commonjs) from 21.0.1 to 22.0.1. - [Release notes](https://github.com/rollup/plugins/releases) - [Changelog](https://github.com/rollup/plugins/blob/master/packages/commonjs/CHANGELOG.md) - [Commits](https://github.com/rollup/plugins/commits/commonjs-v22.0.1/packages/commonjs) --- updated-dependencies: - dependency-name: "@rollup/plugin-commonjs" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.5.5 to 4.7.4. - [Release notes](https://github.com/Microsoft/TypeScript/releases) - [Commits](microsoft/TypeScript@v4.5.5...v4.7.4) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 17.0.23 to 18.0.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [ava](https://github.com/avajs/ava) from 4.0.1 to 4.3.0. - [Release notes](https://github.com/avajs/ava/releases) - [Commits](avajs/ava@v4.0.1...v4.3.0) --- updated-dependencies: - dependency-name: ava dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/HEAD/packages/node-resolve) from 13.1.3 to 13.3.0. - [Release notes](https://github.com/rollup/plugins/releases) - [Changelog](https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md) - [Commits](https://github.com/rollup/plugins/commits/node-resolve-v13.3.0/packages/node-resolve) --- updated-dependencies: - dependency-name: "@rollup/plugin-node-resolve" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
BREAKING CHANGE: rule "prefer-readonly-type" is now deprecated in favor of "prefer-readonly-type-declaration" and "@typescript-eslint/prefer-readonly-parameter-types".
…y-type-declaration
ca371f5
to
9b8277c
Compare
Re #153