typescript 仅提取Partial的填充值< T>并忽略未定义的值

czfnxgou  于 2023-02-05  发布在  TypeScript
关注(0)|答案(1)|浏览(143)

我有一些模型可以跟踪几个页面的“完成”状态(注意,没有一个字段是可选的,这对于这个用例来说是必须的):

interface IncompletPages {
  page1: boolean;
  page2: boolean;
  page3: boolean;
  page4: boolean;
}

在我的组件中,我有一个此接口的本地对象,它控制活动的router-outlet(即,它仅在所有页面完成后才启用主router-outlet)。默认情况下,它们都以false开始,这意味着将使用主router-outlet,但是在创建组件时,API调用将返回IncompletePages的示例,该示例可以将它们中的一些设置为真。

@Component({})
export class MyComponent {

  pagesToComplete: IncompletPages = {
    page1 = false,
    page2 = false,
    page3 = false,
    page4 = false,
  };

  constructor(private mySvc: MyService) {
    mySvc.getIncompletePages().subscribe({
      next: (pages: IncompletePage) => {
        this.pagesToComplete = pages;
      },
    });
  }
}

从这里开始,我希望每个页面在完成时通过发送一个包含其属性和布尔值的对象(但 * 仅 * 包含其属性)来通知pagesToComplete对象。为此,我在服务中添加了一个简单的getter和setter:

export class MyService {
  private complete$: Observable<Partial<IncompletePages>>;
  private comleteSubscriber: Subscriber<Partial<IncompletePages>>;

  constructor() {
    this.complete$ = new Observable<Partial<IncompletePages>>(completeSubsciber => {
      this.completeSubscriber = completeSubsciber;
    });
  }

  getIncompletePages() {
    // return result of API call
  }

  getCompletedNotification() {
    return this.complete$;
  }

  setCompletedNotification(completed: Partial<IncompletePages>) {
    this.completeSubscriber.next(completed);
  }
}

因此,每个页面一旦完成,就应该在完成时执行类似mySvc.setCompletedNotification({page1: true});的操作,这将在服务中的complete$上发出,MyComponent将通过getCompletedNotification()的开放订阅来获取,如下所示:

@Component({})
export class MyComponent {

  pagesToComplete: // ...

  constructor(private mySvc: MyService) {
    // ...
  }

  ngOnInit() {
    this.mySvc
      .getCompletedNotification()
      .pipe(
        tap((pages: Partial<IncompletePages>) => {
          // And here's my question (below)
        })
      )
      .subscribe();
  }
}

现在所有的设置都结束了,我的问题是,有没有一种简洁的方法可以更新pagesToComplete中的一个 * 单个 * 值,而无需重写整个对象?类似于this.pagesToComplete[keyof pages] = [keyof pages].value;?我知道使用<Partial<T>>将使<T>的所有属性都是可选的,并且当发送<Partial<T>>时,它将使所有其他属性都是未定义的。然而,我不想将本地对象中的其他值重置为undefined,而只想更新传递过来的值。
现在,我决定在空合并操作符的帮助下每次重写整个对象:

(pages) => {
  this.pagesToComplete = {
    page1: pages.page1 ?? this.pagesToComplete.page1,
    page1: pages.page2 ?? this.pagesToComplete.page2,
    page1: pages.page3 ?? this.pagesToComplete.page3,
    page1: pages.page4 ?? this.pagesToComplete.page4,
  };
}

但是这感觉是不必要的冗长。

roejwanj

roejwanj1#

如果我没理解错的话,这能行吗?

@Component({})
export class MyComponent {

  pagesToComplete: // ...

  ngOnInit() {
    this.mySvc
      .getCompletedNotification()
      .pipe(
        tap((pages: Partial<IncompletePages>) => {
          this.pagesToComplete = {...this.pagesToComplete, ...pages };
        })
      )
      .subscribe();
  }
}

在操场上检查这个代码

相关问题