问题
Going around in circles here. Very new to Typescript and it's causing major headaches with trivial implementations.
How do a define in AgentStatusService
that it should have an array of 4 options called ['offline','available','busy','away']
? AgentStatus is defined ( or is it? ) and I am injecting it into the AgentStatusService
.
Microsoft Visual Studio Code is barfing on line 21 where the type 'typeof AgentStatus' is not assignable to type 'AgentStatus'... why?
Updated:
import { EventEmitter, Injectable } from '@angular/core';
export enum AgentStatus {
available =1 ,
busy = 2,
away = 3,
offline = 0
}
export interface IAgentStatusService {
state: number
states: AgentStatus
}
@Injectable()
export class AgentStatusService implements IAgentStatusService {
state:number; // this really should be string, but line 22 returns a number
states:AgentStatus;
constructor(states:typeof AgentStatus = AgentStatus){
// unreacheable code browser_adapter.ts:78EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'isSkipSelf' of null
// absolutely impossible to debug...
this.state = AgentStatus.offline // this returns a number
}
// set state(state:string){
// try{
// this._state = this.states[state];
// // string
// } catch(e){
// console.log('tried setting bad enum value on AgentStatus', e.stack);
// }
// }
// get state():string{
// return this._state;
// }
// get model():any {
// return this.states;
// }
}
Compare with This implementation satisfies angular2:
@Injectable()
export class AgentStatusService {
public states = ['offline','available','busy','away'];
private _state;
constructor(){
this._state = this.states[0];
}
set state(state:string){
try{
this._state = this.states[state];
} catch(e){
console.log('tried setting bad enum value on AgentStatus', e.stack);
}
}
get state():string{
return this._state;
}
get model():any {
return this.states;
}
}
回答1:
It's not obvious what you want here, but let me explain a few things...
I have created a blog post talking about this:
How to use TypeScript Enums, especially with Angular 2+
But I'll include all the information inline here:
A enum is just an object. Your enum is written something like this in JavaScript:
{
0: "offline",
1: "available",
2: "busy",
3: "away",
available: 1,
busy: 2,
away: 3,
offline: 0
}
The benefit from typing is very limited in enums.
This line is valid:
var value = <AgentStatus>"offline";
But it's not useful, because
value == AgentStatus.offline // <- false, because it's "offline" == 0
So, you should always store your values as numbers, which you can obtain as follows:
How to convert string to enum
var value = AgentStatus["offline"]; // so value is now 0
// You can also use this, which only gives IDE hints, no runtime benefit
var value: AgentStatus = AgentStatus["offline"];
This makes the previous comparison work:
value == AgentStatus.offline // <- true, because it's 0 == 0
Now, a couple questions remain:
How do you get the string equivalent?
AgentStatus.offline // 0
AgentStatus[AgentStatus.offline] // -> AgentStatus[0] -> "offline"
How do you get all possible enum values?
var options : string[] = Object.keys(AgentStatus);
// The options list has the numeric keys, followed by the string keys
// So, the first half is numeric, the 2nd half is strings
options = options.slice(options.length / 2);
Gotcha
If you write this in your template:
{{AgentStatus[myValue]}}
It will fail, because it doesn't have access to imported types (it gets executed later by Angular).
To make it work, your component will need to have a reference to the enum type / object, something like:
export class MyComponent {
// allows you to use AgentStatus in template
AgentStatus = AgentStatus;
myValue : AgentStatus;
// ...
}
Runnable Demo
Here is an example that explains everything I pointed in here:
http://plnkr.co/edit/vOeeDrCI6CmsXdWaMtwG?p=preview
Look in the file: app/app.component.ts
.
回答2:
Microsoft Visual Studio Code is barfing on line 21 where the type 'typeof AgentStatus' is not assignable to type 'AgentStatus'... why
You have states:AgentStatus = AgentStatus
. Here states:AgentStatus
is actually a value of type AgentStatus where as = AngentStatus
is the whole enum.
Fix
you probably want:
states:typeof AgentStatus = AgentStatus
Or
states:AgentStatus = AgentStatus.Available
More
This is similar to you try to assign foo:SomeClass = SomeClass
instead of foo:SomeClass = new SomeClass()
.
来源:https://stackoverflow.com/questions/37402620/dont-know-how-to-implement-an-enum-using-an-interface-in-an-angular2-class