Issue
I am have a hard time figuring how to make typescript happy with this case:
const t1 = new BehaviorSubject("test");
const t2 = new BehaviorSubject(["test2"]);
function transformString(subject:string):string
function transformString(subject:string[]):string[]
function transformString(subject:string|string[]):string|string[]{
if(Array.isArray(subject)){
return subject.map(t=>t.toUpperCase());
}
return subject.toUpperCase();
}
t1.pipe(map(transformString)); // Type error
t2.pipe(map(transformString));
t1.next(transformString(t1.value));
t2.next(transformString(t2.value));
The type error I am receiving is this:
Argument of type 'OperatorFunction<string[], string[]>' is not assignable to parameter of type 'OperatorFunction<string, string[]>'. Type 'string[]' is not assignable to type 'string'.ts(2345)
I have added the last two lines just to test if the override was working correctly and it does. For now, the only solution I find is to hunt the types at the map level:
t1.pipe(map<string,string>(transformString));
But this is getting redundant since we do know t1's type already. Also, the plan was at first to include the map into a variable, but I left it outside for now.
Edit:
As @Zerotwelve pointed out, the code above can work without using the overloads. I did not catch the real issue from my code in the minimal code above.
The problem comes when this is used in another function:
function t1F(): Observable<string> {
const t1 = new BehaviorSubject("test");
return t1.pipe(map(transformString));
}
Here typescript complains that
Type 'Observable<string | string[]>' is not assignable to type 'Observable<string>'. Type 'string | string[]' is not assignable to type 'string'.
Type 'string[]' is not assignable to type 'string'.
Solution
You can try something like the following:
function transformString<T extends string | string[]>(subject: T): T {
if (Array.isArray(subject)) {
return subject.map((t) => t.toUpperCase()) as T;
}
return subject.toUpperCase() as T;
}
function t1F(): Observable<string> {
const t1 = new BehaviorSubject('test1');
return t1.pipe(map(transformString));
}
function t2F(): Observable<string[]> {
const t1 = new BehaviorSubject(['test2']);
return t1.pipe(map(transformString));
}
Answered By - Amer
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.