27

If I do not want the value of a parameter change within a function scope, is there any way to annotate that with Typescript?

I've tried:

function walk(const fileName: string): string[] {
// -----------^
}

But it does not work.

kiewic
  • 15,852
  • 13
  • 78
  • 101
  • 1
    I don't believe this is currently possible. –  Jul 13 '17 at 16:15
  • At least there is an option to make arrays *readonly*: `function foo(bar: readonly number[]) { }`. This feature is not limited to function declarations, and it converts a mutable array to immutable array. – kiewic Jul 05 '19 at 15:09
  • wwo caveats about that though: 1. It still lets you reassign `bar = ...` (it only prevents `bar[i] = ...` or `bar.pop()`, etc.). 2. `readonly` is shallow so if you have an array of objects instead of simple numbers, it _won't_ prevent `bar[i].whatever = ...`. Unfortunately immutability is an area where TypeScript is still missing a lot of useful stuff! – peterflynn Aug 19 '21 at 01:25
  • If this became possible everyone would start annotating every single argument as `const` by default to be "safe", like we do with variables, and that could get annoying. – Boris Verkhovskiy Nov 14 '22 at 09:26

4 Answers4

8

There is no way to do it right now, and it may not be, as it is not possible in ES6 either:

How to make function parameter constant in JavaScript?

This workaround doesn't work for TypeScript anyway.

lilezek
  • 6,976
  • 1
  • 27
  • 45
  • Got it. Unfortunately, I do not see how the JavaScript workaround can work with Typescript. First, if parameters are not defined, TS complains with `error TS2554: Expected 0 arguments, but got 1`,. Second, the tuple syntax results in `error TS2461: Type 'IArguments' is not an array type`. – kiewic Jul 13 '17 at 16:39
  • @kiewic It doesn't work for TS. I pointed out that is not possible, and using the workaround for TypeScript violates function's argument contract. – lilezek Jul 13 '17 at 16:41
  • My bad, I missed that part of your answer. Thanks for helping. – kiewic Jul 13 '17 at 17:20
  • @kiewic You didn't. It was edited after you comment, as I saw it may not be clear enough. – lilezek Jul 13 '17 at 17:20
3

It's not supported yet, but you can upvote this feature request & follow it for any updates in the future: https://github.com/microsoft/TypeScript/issues/18497

In the meantime your best bet is to use a linter rule to make arguments const by default, like ESLint's no-param-reassign rule. In any rare cases where you need an argument to be not const, you can either use eslint-disable-line each place you reassign it, or wrap the whole function in an eslint-disable / eslint-enable pair to make all its arguments non-const.

peterflynn
  • 4,667
  • 2
  • 27
  • 40
1

A short workaround with a few extra characters gets close:

function fo(args: {x: number,y: string}): void{
    const {x,y} = args;
    x = 2; // Cannot assign to 'x' because it is a constant.ts(2588)
}
function fa(...args: [x: number,y: string]): void{
    const [x,y] = args;
    x = 2; // Cannot assign to 'x' because it is a constant.ts(2588)
}

but you can still overwrite using args.x=2.

Craig Hicks
  • 2,199
  • 20
  • 35
0

Typescript doesn't support const in the function parameter yet, but you can do readonly parameters.

Typescript 3.4 added support for readonly arrays and tuples (not objects yet).

Examples:

function foo(arr: readonly string[]) {}

or

function foo(pair: readonly [string, string]) {}

or

function foo(arr: ReadonlyArray<string>) {}

Sri
  • 4,613
  • 2
  • 39
  • 42
  • 1
    Are you sure, it seems `Readonly` works with objects too: https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlyt – kiewic Jun 27 '20 at 18:02