0

To define a function type, below example does not allow const

interface Square{
    readonly color: string;
    readonly area: number;
}

interface compareTo{
    (const v1: Square, const v2: Square): number;  // syntax error      
}

How to compare v1 & v2 without changing the pointer of an object(Square) it is pointing to?

5
  • 4
    How is this 'const' supposed to work? Why should function argument be const? It doesn't matter whether it's const or not inside function. Commented May 2, 2018 at 16:42
  • 4
    Possible duplicate of Can a typescript parameter be annotated as const? Commented May 2, 2018 at 16:48
  • @estus Interface implementation should make sure that v1 and v2 objects are only read but not written. here is a scenario Commented May 2, 2018 at 17:03
  • 1
    It's unclear what 'read' and 'written' is about in your case. const doesn't prevent objects from being modified, as the answer explains. Please, provide an example that shows what you're trying to achieve/avoid. Commented May 2, 2018 at 17:07
  • @estus Query edited Commented May 2, 2018 at 17:18

2 Answers 2

3

There's no way to declare this because it would have no effect on anything. const in TypeScript doesn't mean immutable -- it applies only to a binding, and a function parameter is not an externally-visible binding.

Sign up to request clarification or add additional context in comments.

Comments

1

As another answer explains, const doesn't prevent objects from being modified in ES6, it only prevents reassignments.

In order to prevent parameter reassignments globally, TSLint no-parameter-reassignment rule can be used.

In order to prevent object modifications at runtime, Object.freeze should be used. This can be enforced at compilation time with Readonly mapped type. However, this won't have any effect if the types are compatible:

interface compareTo {
    (v1: Readonly<Square>, v2: Readonly<Square>): number;      
}
const foo: compareTo = (a: Square, b: Square) => {
  a.area = 0;
  return 1;
}   

Generally, this isn't the responsibility of an interface to tell how function should internally work, it just describes its interface, so it would be:

interface compareTo {
    (v1: Square, v2: Square): number;      
}
const foo: compareTo = (a: Readonly<Square>, b: Readonly<Square>) => {
  a.area = 0; // error
  return 1;
}   

But this will work if types are inferred from generic type, i.e. a type isn't specified in compareTo implementation:

interface compareTo<T = Readonly<Square>> {
    (v1: T, v2: T): number;      
}

const foo: compareTo = (a, b) => {
  a.area = 0; // error
  return 1;
}   

6 Comments

interface should be able to tell whether v1 can be modified. We do this in Java, C. Anyways, let foo:compareTo = (a: Readonly<Square>, b: Readonly<Square>) => {a = {color: 'red', area: 20}; return 1;} allows modification
As I mentioned, an interface only describes function inputs and outputs, not how function works. It's possible to do that with Readonly but not necessarily necessary. JS semantics differs from the C++ example you've linked because objects are passed by reference everywhere in JS, and you can't restrict a developer from shooting into the foot everywhere. Common JS methods like array map, filter, sort aren't typed to prevent object modifications, even though it's rarely a good idea there.
I do not get all three example in this answer, because interface Square{readonly color: string; readonly area: number;} would suffice for not allowing a.area=0. I did not get the value-add of using Readonly<Square>
I was under impression that you wanted to omit readonly fields in Square and enforce them in compareTo only. If you didn't, it still remains unclear what purpose const is supposed to serve in your case.
I would not like to allow something like this... a = {color: 'white', area: 20}; in the function. const helps in such scenario for variables unlike parameters.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.