Let's say i have a User class and i need to instance only predefined 'status'. Is this the best way to do it? Is there any other alternative? What`s the right way to do it? Thanks in advance.
export class User {
constructor(
username: string,
email: string,
status: AccountStatus
){}
}
export enum AcountStatus {
Active = 'Active',
Suspended = 'Suspended'
}
import { User } from 'app/models/user.model'
import { AccountStatus } from 'app/models/user.model'
private user: User;
this.user = new User('username', '[email protected]', AccountStatus.Active)
CodePudding user response:
If most of the users will have a default Active
status, then you can give a default value to status
in the constructor as well:
class User {
constructor(
public username: string,
public email: string,
public status: AccountStatus = AccountStatus.Active
){}
}
Then when you initialize an Active user, you don't need to explicitly pass in the Active
status every time:
let user: User;
user = new User('username', '[email protected]')
Another possible improvement is you can replace the AccountStatus
enum with a union type:
class User {
constructor(
public username: string,
public email: string,
public status: 'Active' | 'Suspended' = 'Active'
){}
}
let user = new User('username', '[email protected]')
CodePudding user response:
If you want to give the consumer of your code more flexibility, you can accept either a union of string literals OR a member from your string enum:
type Values<T> = T[keyof T];
type StringEnumToUnion<T extends Record<string, string>> = `${Values<T>}`;
function valueIsStringEnum <Enum extends Record<string, string>>(
value: unknown,
o: Enum,
): value is Values<Enum> {
return Object.values(o).includes(value as string);
}
function assert (expr: unknown, msg?: string): asserts expr {
if (!expr) throw new Error(msg);
}
export enum AccountStatus {
Active = 'Active',
Suspended = 'Suspended',
}
export class User {
constructor (
username: string,
email: string,
status: StringEnumToUnion<typeof AccountStatus>,
) {
let ac: AccountStatus;
ac = status; /*
~~
Type '"Active" | "Suspended"' is not assignable to type 'AccountStatus'.
Type '"Active"' is not assignable to type 'AccountStatus'.(2322) */
// Assert it back to AccountStatus for your own usage if you want:
assert(valueIsStringEnum(status, AccountStatus));
ac = status; // ok
}
}
// Example usage:
new User('user', '[email protected]', 'ACTUVE'); /*
~~~~~~~~
Argument of type '"ACTUVE"' is not assignable to parameter of type '"Active" | "Suspended"'.(2345) */
new User('user', '[email protected]', 'Active'); // ok
new User('user', '[email protected]', AccountStatus.Active); // ok