简体   繁体   中英

Typescript/Angular: Updating a Getter/Setter type casting in an extended class/component

I've attempted to dumb this down, so the use case for wanting this is less clear but the problem remains.

Problem: Being unable to expand/update/declare enums or types within a class

Goal: Rather than rewriting the getter/setter in extended class's with the new type whenever 'ValidState' deviates from the default in the base class, is there a way to do this so the getter/setters would be aware of the new type?

Example Base Class

import { Component, OnInit } from '@angular/core';

export enum DefaultValidStates {
  LOADING = 'LOADING',
  READY = 'READY',
}

type ValidState = DefaultValidStates;
// Is there a way for this to be within a class so it can be updated in extended classes and still trigger type checks

@Component({
  selector: 'app-base',
  template: '<p>BaseComponent status = {{status}}</p>',
})
export class BaseComponent implements OnInit{
  private _status: ValidState | undefined;

  constructor(
  ) {
  }

  ngOnInit() {
    this.status = DefaultValidStates.LOADING;
    window.setTimeout(() => {
      this.status = DefaultValidStates.READY;
    }, 3000)
  }

  get status(): ValidState | undefined {
    return this._status;
  }

  set status(status: ValidState | undefined) {
    this._status = status;
  }
}

Example Extended Class

import { Component} from '@angular/core';
import {BaseComponent, DefaultValidStates} from "../base/base.component";

enum OtherValidStates {
  FATAL_ERROR = 'FATAL_ERROR',
}

type ValidState = DefaultValidStates | OtherValidStates;
// Is there someway to pass/use this new type so the base class knows of it

@Component({
  selector: 'app-other',
  template: '<p>OtherComponent status = {{status}}</p>',
})
export class OtherComponent extends BaseComponent{
  
  constructor() {
    super();
  }

  ngOnInit() {
    this.status = DefaultValidStates.LOADING;
    window.setTimeout(() => {
      this.status = OtherValidStates.FATAL_ERROR;
      // Because ValidState is what is set in BaseComponent this won't compile
      // Type 'OtherValidStates' is not assignable to type 'DefaultValidStates | undefined'.
    }, 3000)
  }
}

Cheers,

Edits: Attempting to clarify issue.

Possible Solution

Base Class

import { Component, OnInit } from '@angular/core';

export enum DefaultValidStates {
  LOADING = 'LOADING',
  READY = 'READY',
}

@Component({
  selector: 'app-base',
  template: '<p>BaseComponent status = {{status}}</p>',
})
export class BaseComponent<States = undefined, ValidStates = States> implements OnInit{

  constructor() {}

  ngOnInit() {
    this.status = DefaultValidStates.LOADING;
    window.setTimeout(() => {
      this.status = DefaultValidStates.READY;
    }, 3000)
  }

  private _status: DefaultValidStates | ValidStates | undefined;

  get status(): DefaultValidStates | ValidStates | undefined {
    return this._status;
  }

  set status(status: DefaultValidStates | ValidStates | undefined) {
    this._status = status;
  }
}

Extended

import {Component, OnInit} from '@angular/core';
import {BaseComponent, DefaultValidStates} from "../base/base.component";

enum OtherValidStates {
  FATAL_ERROR = 'FATAL_ERROR',
}

@Component({
  selector: 'app-other',
  template: '<p>OtherComponent status = {{status}}</p>',
})
export class OtherComponent extends BaseComponent<OtherValidStates> implements OnInit {
  constructor() {
    super();
  }
  ngOnInit() {
    this.status = DefaultValidStates.LOADING;
    window.setTimeout(() => {
      this.status = OtherValidStates.FATAL_ERROR;
    }, 3000)
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM