Reputation: 442
I need to define an object that has an array of strings, but the string can only accept certain values. The examples below are the possible scenario:
let user = {
name: 'John',
communicationPreferences: ['email', 'whatsApp']
}
or
let user = {
name: 'John',
communicationPreferences: ['whatsApp', 'weChat', 'skype']
}
or
let user = {
name: 'John',
communicationPreferences: ['email', 'whatsApp', 'weChat', 'skype', 'line', 'sms']
}
Upvotes: 1
Views: 138
Reputation: 2085
You have a some options depending on your exact situation:
Enum: Provides flexible, type-safe definition of your values that allow for run-time look-ups and reverse look-ups. This is likely your preferred solution:
enum Channel {
Email = 'email', // if you prefer email = 'email', etc. that's also very doable
WhatsApp = 'whatsApp',
WeChat = 'weChat',
Skype = 'skype',
Line = 'line',
SMS = 'sms',
}
class User {
constructor(private name: string, private communicationPreferences: Channel[]) { };
}
const john = new User('john', [Channel.SMS]); // {name: 'john', communicationPreferences: ['sms']);
// example of reverse look-up
const channel = 'skype'; // from some unverified source
if (Channel[channel] === undefined) {
// handle error case at run-time
}
Union Type: If you wanna be quick and dirty about it, you can use a string literal union type. This would provide compile-time only safety, or if you have a very extreme case where you want to limit the (very small) overhead of an Enum:
type Channel = 'email'| 'whatsApp'| 'weChat' | 'skype' | 'line'| 'sms';
interface User {
name: string;
communicationPreferences: Channel[];
}
const john: User = {
name: 'john',
communicationPreferences: ['telegraph']; // would fail to compile
}
Index Type: Your last option would be combining the keyof
and typeof
operators to produce a dynamic union type. This might be useful if your communication channel options are coming from an external JSON/JS file, especially if it may change:
// Some example object you're getting
const channels = {
skype: { ... },
sms: { ... },
line: { ... },
// and so on
}
// in your script
type Channel = keyof typeof channels; // "skype" | "sms" | "line" | ...
In your situation, you might also be interested in the Set
class; it provides a distinct (only one of each value allowed) collection:
// define Channel type, from options above
class User {
private communicationPreferences: Set<Channel>;
constructor(private name: string, channels: Channel[]) {
this.communicatonPreferences = new Set<Channel>(channels);
}
public serialize() {
return {
name: this.name,
communicationPreferences: Array.from(this.communicationPreferences)
}
}
}
Upvotes: 1
Reputation: 869
Typescript allow usage of Enum:
export enum communicationPreferences{
whatsApp=0
weChat=1
skype=2
}
var value: communicationPreferences=communicationPreferences[communicationPreferences.whatsApp]
beware of trying to use something like communicationPreferences.whatsApp by itself which returns the integer value.
seems like typescript 2.4 now support string-based enum so we dont even need to do the integer stuff and just declare whatsApp="whatsApp"
Upvotes: 0
Reputation: 21337
type CommunicationPreferences = 'email' | 'whatsApp' | 'weChat' | 'skype' | 'line' | 'sms';
interface User {
name: string;
communicationPreferences: CommunicationPreferences[];
}
let user : User = {
name: 'John',
communicationPreferences: ['email', 'whatsApp', 'weChat', 'skype', 'line', 'sms']
}
Upvotes: 0
Reputation: 327
To achieve this I would build a strongly Typed object using Enums like this:
export enum ChannelCommunication {
whatsApp = 'whatsApp',
weChat = 'weChat',
skype = 'skype',
email = 'email',
line = 'line',
sms = 'sms'
}
export class User {
private _name: String;
private _communicationPreferences: ChannelCommunication[];
constructor(name:String, communicationPreferences: Array<ChannelCommunication>) {
this._name = name;
this._communicationPreferences = communicationPreferences;
}
public name: String;
public communicationPreferences: ChannelCommunication[]
}
let communicationPreferences: ChannelCommunication[] = [ChannelCommunication.email,
ChannelCommunication.line,
ChannelCommunication.skype,
ChannelCommunication.sms,
ChannelCommunication.weChat,
ChannelCommunication.whatsApp];
let user = new User('John',communicationPreferences);
Hope it answers your question
Upvotes: 0