如何声明必须返回其参数之一的函数的签名? (任何语言*)

How does one express the signature for a function that must return an argument (or this) that it receives (is called on), in TypeScript? Is there a programming language where this is possible?*

// In TypeScript (or consider it pseudo-code)
class C {
  // EXAMPLE 1 – Not polymorphic
  chainable(x): this                 // MUST not only return some C,
  {}                                 // but the same instance it was called on
}
// EXAMPLE 2
function mutate<T>(a: T[], x): T[]   // MUST return a, not a new Array
{
  /* So that this doesn't compile */ return Array.from(a);
  /* But this is OK */               return a;
}

Conversely, how about a function that must return a new instance?

// EXAMPLE 3
function slice<T>(a: T[], x, y): T[] // MUST return a new Array

❌TypeScript


Go 2?

Would the following contract achieve the above?

contract referentiallyIdentical(f F, p P) {
  f(p) == p
  v := *p
}
type returnsSameIntSlice(type T, *[]int referentiallyIdentical) T
func main() {
  var mutate returnsSameIntSlice = func(a *[]int) *[]int {
    b := []int{2}
    /* Would this compile? */ return &b
    /* This should */         return a
  }
}  

C++20?

Could the above be expressed as a C++ concept?


✅Scala


*Originally, the question was about doing this in TypeScript, but since that isn't possible, I am curious if it is in another language.

Feel free to remove a tag if that language's type system can't express this

You can - in Scala.

Class with a method returning this.type:

class C {
  var x = 0 

  /** Sets `x` to new value `i`, returns the same instance. */
  def with_x(i: Int): this.type = {
    x = i
    this   // must be `this`, can't be arbitrary `C`
  } 
}

In-place sort that guarantees to return exactly the same array (doesn't really sort anything here):

def sortInPlace[A: Ordered](arr: Array[A]): arr.type = {
  /* do fancy stuff with indices etc. */
  arr
}

If you attempt to return a different array,

def badSortInPlace(arr: Array[Int]): arr.type = Array(1, 2, 3) // won't compile

you'll get an error at compile time:

error: type mismatch;
found   : Array[Int]
required: arr.type
      def badSortInPlace(arr: Array[Int]): arr.type = Array(1, 2, 3)
                                                           ^

This is called a singleton type, and is explained in the spec.

In a language with parametric polymorphism, any function of the type

a → a

must be the identity function: since the function is polymorphic in a, it cannot possibly know anything about a, in particular, it cannot possibly know how to construct an a. Since it also doesn't take a world value or an IO monad or something equivalent, it cannot get a value from global state, a database, the network, storage, or the terminal. It also cannot drop the value, since it must return an a.

Ergo, the only thing it can do is to return the a that was passed in.