rxjs map 无法通过重载提示类型到项目函数,如果没有显式定义会导致类型错误

rxjs map cannot hint type to project function with overload, causing type errors if not explicitly defiend

我很难弄清楚如何让打字稿对这种情况感到满意:

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));

我收到的类型错误是这样的:

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)

我添加了最后两行只是为了测试覆盖是否正常工作并且确实如此。目前,我找到的唯一解决方案是在地图级别寻找类型:

t1.pipe(map<string,string>(transformString));

但这变得多余了,因为我们已经知道 t1 的类型了。另外,最初的计划是将地图包含到一个变量中,但我暂时把它放在外面了。

编辑:

正如@Zerotwelve 所指出的,上面的代码可以在不使用重载的情况下工作。在上面的最小代码中,我没有从我的代码中发现真正的问题。

在另一个函数中使用时出现问题:

function t1F(): Observable<string> {
  const t1 = new BehaviorSubject("test");
  return t1.pipe(map(transformString));
}

这里打字稿抱怨

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'.

你可以这样做:

const t1 = new BehaviorSubject("test");
const t2 = new BehaviorSubject(["test2"]);

function transformString(subject:string|string[]):string|string[]{
  if(Array.isArray(subject)){
    return subject.map(t=>t.toUpperCase());
  }
  return subject.toUpperCase();
}

t1.pipe(map(transformString));
t2.pipe(map(transformString));

您可以尝试以下操作:

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));
}