How can I create the type from existed function in Dart/Flutter?
I know typedef can create custom type, something like:
typedef Custom<T> = int Function(T a, T b)
But if I have a function from the dependency and want to create the type for arguments, how can I do this?
int functionFromDependency(String a, {int b, ComplexType c}) {
// ...
}
// something syntax like `typeof<functionFromDependency>`
void myProcess(typeof<functionFromDependency>? runner) {
(runner ?? functionFromDependency)(
a,
b: b,
c: c
);
}
It is helpful for testing which can inject custom function.
Dart doesn't have something like C++'s decltype that would allow you to statically re-use the type of some other variable.
In the case of a callback argument to a function, I don't think that it would make sense anyway. For example, you could give up static type-checking and do:
void myProcess(Function? runner) {
(runner ?? functionFromDependency)(
a,
b: b,
c: c
);
}
but ultimately myProcess still requires that runner be a function that can takes a single positional argument and that can take named parameters b and c, all with types appropriate for the supplied arguments. You might as well do:
typedef MyProcessCallback = void Function(A a, {B b, C, c});
void myProcess(MyProcessCallback? runner) {
...
}
myProcess should not be trying to conform to its callers; that's backwards. Callers of myProcess should be conforming to myProcess's API instead, which is much easier.
Related
I am writing a custom mixin routine, it accepts varags of objects:
type HasIndex = {[key:string]:any};
// type RetType = ?
const mixinAll = (...v: HasIndex[]): RetType => {
return v.reduce((a,b) => doMixing(a,b,new Set()), {});
});
so my question is - how can I represent the return value for mixinAll? Is there a way to represent a mixin type with TypeScript? Very similar to doing the same for Object.assign.
If you look at the definition for Object.assign, that pretty much answers the question:
interface ObjectConstructor {
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
}
in short, use the & operator to create an intersection type - unfortunately can't seem to create something finer-grained than that.
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.
In essence, four questions are here for Golang interfaces, with each one slightly harder than the one before it.
say we imported a lot of interfaces, A, B, C, ..., G
import (
"A",
"B",
"C",
// more ...
"G"
)
and we define a type S:
type S struct {
// more ...
}
now if S "implements" one of the interfaces:
func (s S) Foo() {
// more ...
}
Up to date, is there any other way to tell which interface of A - G does S implement, except for looking and searching into interface declarations of A - G? If no, is there a way to explicitly tell S to implement which interface? So far, it appears that the which interface S implemented is inferred.
If, for the same example, B, C, D interfaces all have the Foo() method with the same signature. In this case, which interface does S implement? Does it depend on the order those interfaces are imported from B, C, and D?
If, rather than importing interfaces, we declare and define interfaces B, C, D in the same file, but those interfaces again all have Foo() method with the same signature, which interface does S implement? Does it depend on the order those interfaces are declared, or defined?
If, we declared and defined B, C, D interfaces in the same file, B has Foo() method, C has Bar() method, and D has both Foo() and Bar(). Now if S implement Foo() and Bar(), then does S implement B and C, or S only implements D?
No. (But as a side note, you don't import interfaces, you import packages.)
All of them. Order doesn't matter. If you declared variables of type B, C, and D, all of them would be able to hold an S.
All of them. What you do in the same or different files doesn't matter.
All of them. S implements B because S has Foo(). S implements C because S has Bar(). S implements D because S has both Foo() and Bar().
I'm having trouble wrapping my head around how to make this method reusable:
trait T
case class A extends T
case class B extends T
def deserialize(source:Json):A = {
source.convertTo[A]
}
The .convertTo[x] method can convert into both A and B; however, at the moment this method can only produce A. How to specify what type to convert to when calling the method?
Clarification:
At the moment I could do this, but it's redundant, especially when the number of T subclasses grow:
def deserialize_A_(source:Json):A = {
source.convertTo[A]
}
def deserialize_B_(source:Json):B = {
source.convertTo[B]
}
How to merge these two methods into one, so that it would handle all subclasses of T? (Note: presume that the nested method convertTo can already handle all these subclasses.)
Because it's easier to show than explain (I presume the way I wrote it won't work):
def deserialize(source:Json, subclassToConvertTo:SubclassOfT):SubclassOfT = {
source.convertTo[subclassToConvertTo]
}
I'm not sure what library you are using, but if you look at convertTo type signature, you'll see what needs to be done. For instance, spray-json has a convertTo method that looks like this:
def convertTo[T : JsonReader]: T
The notation T : JsonReader is a context bound, a syntactic sugar for this:
def convertTo[T](implicit $ev : JsonReader[T]): T
So, basically, you need to receive a type parameter (like the T above), and an implicit value based on that type parameter, whose type depends on what convertTo on the library you are using needs. Let's say it is JsonReader, then your method becomes:
def deserialize[X : JsonReader](source:Json): X = {
source.convertTo[X]
}
Which you need to call like this, because X cannot be inferred:
deseralize[A](someSource)
If you need X to be a subtype of T, you can add that restriction like this:
def deserialize[X <: T : JsonReader](source:Json): X = {
source.convertTo[X]
}
PS: I'd really rather you didn't use things like T, A and B as types in your example, since they are common identifiers for type parameters.
def deserialize[T <: A : JsonReader](source : Json) = source.convertTo[T]
This is just a simple matter of parametrizing the method on the type of result you want. It should be covered fairly early in any book on Scala.
See for example http://twitter.github.io/scala_school/type-basics.html#parametricpoly
Explained with an example:
class A {
def f = {
val b: B = C.factory(this).asInstanceOf[B]
}
class B
}
object C {
def factory(a: A): A#B = new a.B
}
C.factory is a function for creating a new instance of an A#B. Since B is a nested type, I've included an A reference in the function signature. The calling function f has to cast the reference returned from factory, which I'd like to avoid. Without the cast I get:
error: type mismatch;
found : A#B
required: A.this.B
It depends on what you want. In A, B means this.B, that is a B that is created from the enclosing instance. Indeed your factory returns that, but it does not say so. It just says it returns the A#B (called a type projection), a B of some unspecified A instance. If, for your val b, you don't care by which A instance it was created, then you should say so with val b: A#B (or let the compiler infer it).
If you do care that it is a B from your A and no other, you might be out of luck. Your factory returns an instance of B created by the a parameter. But your signature does not says so. You would want a.B rather than the less precise type projection A#B. Alas, the language does not allow that. You will get an error illegal dependent method type: when you write a dependent type a.B, a must be a "stable identifier" and a method parameter is not considered one. Maybe this blog post may help