Reputation: 2068
I have following situation in typescript:
type Matcher<T, U> = {
First: (arg: T) => U,
Second: () => U
};
class Main<T> {
constructor(private value: T) {
}
match<U>(matcher: Matcher<T, U>): U {
return this.value
? matcher.First(this.value)
: matcher.Second();
}
}
const main = new Main(10);
const res = main.match({ // there is a problem
First: v => v + 10,
Second: () => console.log()
});
So I have an object that user have to pass to the match
method of class instance. This object should contain two functions: First
and Second
. This functions returns value of one type (e.g. number
) or of one type + void
(e.g. number
+ void
), but nothing else. There cannot be string
+ number
types.
This code fails with error
The type argument for type parameter 'U' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
Type argument candidat 'void' is not a valid type argument because it is not a supertype of candidate 'number'.
I understand why this error happens (U
is the single type, but functions have two different types and they cannot be merged and so on), but how can I solve this problem? I need:
any
typevoid
in one or both. number
and string
as returning types are not allowed.Is it possible to do with typescript type system?
Upvotes: 0
Views: 119
Reputation: 164397
You can use union types:
type Matcher<T, U> = {
First: (arg: T) => U;
Second: () => U | void
};
I added the void
just to the second function, but you can have it in the first as well.
But you will then need the match
method to return | void
as well:
match<U>(matcher: Matcher<T, U>): U | void {
return this.value
? matcher.First(this.value)
: matcher.Second();
}
If I understand you correctly, then this might help:
type Matcher<T, U> = {
First: (arg: T) => U;
Second: () => U;
};
type MatcherOne<T, U> = {
First: (arg: T) => void;
Second: () => U;
};
type MatcherTwo<T, U> = {
First: (arg: T) => U;
Second: () => void;
};
class Main<T> {
constructor(private value: T) { }
match<U>(matcher: Matcher<T, U>): U;
match<U>(matcher: MatcherOne<T, U>): U | void;
match<U>(matcher: MatcherTwo<T, U>): U | void;
match<U>(matcher: Matcher<T, U> | MatcherOne<T, U> | MatcherTwo<T, U>): U | void {
return this.value
? matcher.First(this.value)
: matcher.Second();
}
}
Upvotes: 1