Fix generic type to the type of the first parameter

kotlin type inference failed the value of type parameter k
type inference failed not enough information to infer parameter r in
java generic method parameter example
java generic return type method example
c# reflection generic type
typescript infer generic type
typescript generic function type
c# get generic type

I want to write an extension function which will be available on any type and accept parameter of the same type or subtype, but not a completely different type.

I tried naive approach but it didn't work:

fun <T> T.f(x: T) {
}

fun main(args: Array<String>) {
  "1".f("1") // ok
  "1".f(1) // should be error
}

It seems that compiler just uses Any for T. I want T to be fixed to receiver type.

The only way to do it requires telling the compiler what you want.

fun <T> T.f(x: T) {
}

In order to use it, you have to tell Kotlin what you want the type to be.

"1".f<String>("2")  // Okay
"1".f(2)  // Okay (see voddan's answer for a good explanation)
"1".f<String>(2)  // Fails because 2 isn't a String
"1".f<Int>(2)  // Fails because "1" isn't an Int

Is it possible to fix generic type to the type of the first parameter , I want to write an extension function which will be available on any type and accept parameter of the same type or subtype, but not a completely  TypeScript 2.3 implemented generic parameter defaults which allow you to specify default types for type parameters in a generic type. In this post, I want to explore how we can benefit from generic parameter defaults by migrating the following React component from JavaScript (and JSX) to TypeScript (and TSX):

When you call fun <T> T.f(x: T) {} like "1".f(1), the compiler looks for a common super-type of String and Int, which is Any. Then it decides that T is Any, and issues no error. The only way to influence this process is to specify T explicitly: "1".f<String>(1)

Since all the checks are performed by the compiler, the issue has nothing to do with type erasure.

Java - Generics, The first procedure in this section examines generic types. To examine a generic type and its type parameters The array must contain the correct number of Type objects, in the same order as they appear in the type  The principle difference is that a generic type has a list of Type objects representing its generic type parameters. The first procedure in this section examines generic types. You can create a Type object that represents a constructed type by binding type arguments to the type parameters of a generic type definition. The second procedure

Your issue is like saying "John is 3 years older than Carl, and Carl is 3 years younger than John" ... you still don't know either of their ages without more information. That's the type of evidence you gave the compiler and then you expected it to guess correctly. The only truth you can get from that information is that John is at least 3 years old and Carl is at least 1 day old.

And this type of assumption is just like the compiler finding the common upper bounds of Any. It had two strong literal types to chose from and no ability to vary either. How would it decide if the Int or String is more important, and at the same time you told it that any T with upper bounds of Any? was valid given your type specification. So the safe answer is to see if both literals could meet the criteria of T: Any? and of course they do, they both have ancestors of Any. The compiler met all of your criteria, even if you didn't want it to.

If you had tie-breaking criteria, this would work out differently. For example, if you had a return type of T and a variable of type String receiving the value, then that would influence the decision of Type inference. This for example produces an error:

fun <T: Any> T.f2(x: T): T = x

val something: String = "1".f2(1) // ERROR

Because now the type T is anchored by the "left side" of the expression expecting String without any doubt.

There is also the possibility that this could also be an type inference issue that is not intended, check issues reported in YouTrack or add your own to get a definite answer from the compiler team. I added a feature request as KT-13138 for anchoring a specific type parameter to see how the team responds.

Generic Methods (The Java™ Tutorials > Learning the Java , Here's a first attempt: c) { for (Object o : a) { c.add(o); // compile-time error } } Notice that we don't have to pass an actual type argument to a generic method. Now if you try to intialize the above Lesson class using a non-reference type as its parameter, like int , you will get a compilation error: The type ‘int’ must be a reference type in order to use it as parameter ‘T’ in the generic type or method ‘Lesson’ You can only call it with a reference type, like string or any class.

You can fix T to the receiver type by making f an extension property that returns an invokable object:

val <T> T.f: (T) -> Unit
    get() = { x -> }

fun main(vararg args: String) {
    "1".f("1") // will be OK once KT-10364 is resolved
    "1".f(1) // error: The integer literal does not conform to the expected type String
}

Unfortunately "1".f("1") currently causes an error: "Type mismatch: inferred type is String but T was expected". This is a compiler issue. See KT-10364. See also KT-13139. You can vote on and/or watch the issues for updates. Until this is fixed you can still do the following:

"1".f.invoke("1")
/* or */
("1".f)("1")
/* or */
val f = "1".f
f("1")

Details of the object model, By modifying our generic method to include this bounded type parameter, compilation will now fail If bound A is not specified first, you get a compile-time error:. Generic Methods and Bounded Type Parameters Bounded type parameters are key to the implementation of generic algorithms. Consider the following method that counts the number of elements in an array T[] that are greater than a specified element elem .

How to: Examine and Instantiate Generic Types with Reflection , The first way is to pass all of the arguments, including the type argument, to the Here we explicitly set T to be string as one of the arguments to the function call,  These type variables are known as the formal type parameters of the constructor. The form of the formal type parameter list is identical to a type parameter list of a generic class or interface. Motivation. The following block of Java code illustrates a problem that exists when not using generics. First, it declares an ArrayList of type Object.

Generic Methods (The Java™ Tutorials > Bonus > Generics), In typescript if I try to define them I get an error, "Duplicate identifier Action And action.type (the first generic) is inferred from the first argument. generic-spacing. The --fix option on the command line automatically fixes problems reported by this rule. Enforces consistent spacing within generic type annotation parameters. This rule takes one argument. If it is 'never' then a problem is raised when there is a space

Bounded Type Parameters (The Java™ Tutorials > Learning the , T stands for Type, and is commonly used as the first type variable name when defining generics. Caveat: If we had a generic return type that no arguments were typed this will cause an errorfunction identity<T>(arg: T): T { A type contains a delegate that returns void and whose signature contains two parameters (the first an object and the second a type that is assignable to EventArgs), and the containing assembly targets .NET. By default, this rule only looks at externally visible types, but this is configurable. Rule description

Comments
  • The compiler works according to kotlin semantics, so this is not really "helping", but rather "guidening"
  • Also the term "erasure" is misused here, I believe