2

Is there any way, with a macro library, an eslint rule, a tsconfig setting, a magic global.d.ts file, or otherwise, to make function arguments readonly by default?

// I want the compiler to turn this:
function foo(a: A[], b: Record<string, string> {
}
// Into this
function foo(a: ReadonlyArray<A>, b: Readonly<Record<string, string>> ) {
}
6
  • You want something that transforms your code into invalid TypeScript automatically? There's no way to say readonly b: number as a function parameter. What do you mean by that? That nobody should be allowed to reassign a value to the b variable inside the function body? If so, there's no facility for that, and ReadonlyArray<A> doesn't do that for a either. I'm confused; help! Commented Oct 7, 2021 at 4:07
  • Maybe you're looking for eslint.org/docs/rules/no-param-reassign ? But that's not achievable by any TS syntax. Commented Oct 7, 2021 at 4:09
  • Sorry, ignore the number case. Was thinking only of mutable arguments. When I started writing the question I had foo(args: {a: number, b: string}). That eslint rule seems useful to but my Q is about having functions not mutate mutable parameters. Commented Oct 7, 2021 at 4:50
  • 1
    npmjs.com/package/eslint-plugin-functional Commented Oct 7, 2021 at 5:52
  • You want something that transforms a Record<string, string>into a ReadonlyMap<string, string>? Those are different data structures entirely. Should the transformation also modify property accesses so that something like b.bar turns into b.get("bar")? Could you triple check what you're asking for and make sure that the code in your question constitutes a minimal reproducible example? Commented Oct 7, 2021 at 13:18

2 Answers 2

2

Check out the no-param-reassign ESLint rule:

This rule aims to prevent unintended behavior caused by modification or reassignment of function parameters.

However this is not a replacement for readonly:

/* eslint no-param-reassign: ["error", { "props": true, "ignorePropertyModificationsForRegex": ["^mut"] }] */
function f(n: number, nums: number[], o: { p: string }, mutArr: number[]) {
    n = 10 // error
    n++ // error
    for (n in nums) { } // error
    nums[1] = 10 // error
    nums.push(1) // passes
    nums.sort() // passes
    o.p = 'foo' // error
    mutArr[0] = 10 // passes
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is great it also works for object/array properties. Main thing it's missing is array methods. Thanks a lot, I'll update the example.
Yes, thanks for mentioning that Luke. I've updated the answer.
1

There is an open feature request being actively discussed in the typescript github repo for exactly this feature:

https://github.com/microsoft/TypeScript/issues/42357

It looks like the question of how to deal with untyped library code complicates the feature, so it could be a while before they decide whether or not to add it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.