在打字稿中使用枚举的命名空间
working with namespace for enum in typescript
我正在做 angular 项目,所以我们在这里使用打字稿。
我有一个状态枚举
export enum Status {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
这里的 properties/fields 是重复的,因为它在 serialization/deserialization 中有帮助,如果没有 Status.ACTIVE
就变成 0
的顺序。
现在为了显示目的,我们需要映射可表达的词,比如,
'ACTIVE'-> 'Active'
.
为此我们使用了命名空间,
export namespace Status {
export function displayName(s: Status){
const mapping = {Status.ACTIVE: 'Active', ...}; // I know this can declared at some other places so we don't need to re-initialize every time this function is called.
return mapping[s];
}
}
这使得 Status
的使用变得非常简单。因为现在我可以拥有 Status.ACTIVE
以及 Status.displayName(s)
。基本上使用相同的“classname”状态。 (当然两者都在 status.ts 文件中定义)
现在由于默认 lint 建议删除命名空间。
'namespace' and 'module' are disallowed (no-namespace)
我了解到命名空间是在 ES6 模块系统尚未到位时创建的。所以现在 classes 比名称空间更有意义。但就我而言 - 枚举的上下文
问题是,
- 命名空间的使用是否会产生任何性能、优化或任何其他问题?
- 有没有更好的方法来完成同样的事情(使用相同的“class”名称)
- 不创建命名空间并导出另一个以相同方式工作的函数 - 在同一个文件中运行但没有命名空间;那是解决方案吗?并且基本上不满足我最初要求具有相同 class 名称的要求。
喜欢关注
status.ts
export Status {
ACTIVE = 'ACTIVE'
}
export function statusToDisplayName(s: Status){
const map = {...};
return map[s];
}
usage.ts
import {Status, statusToDisplayName} from 'some/path/status';
...
status = Status.ACTIVE;
statusToDisplay = statusToDisplayName(status);
命名空间与 ES 模块
命名空间被认为已弃用,取而代之的是 ES 模块。它不会导致任何性能或优化问题,但在与 ES 模块一起使用时肯定会造成一些混乱。
作为命名空间的 ES 模块
您可以使用 ES 模块作为命名空间来实现类似的结果
// Status.ts
export enum Status {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
export function toDisplayName(s: Status){
const map = {...};
return map[s];
}
// some-other-module.ts
import * as StatusModule from './Status.ts'
const active = StatusModule.Status.ACTIVE;
const displayname = StatusModule.toDisplayName(active);
如果您希望状态为 'on the same level' 且具有 toDisplayName
功能,您可以考虑以下选项
// Status.ts
enum Status {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
export const ACTIVE = Status.ACTIVE;
export const DEACTIVE = Status.DEACTIVE;
export function toDisplayName(...){...}
但我不推荐,因为会导致代码重复
备选
为了保持所需的结构,您可以尝试使用静态道具class声明一个
// Status.ts
enum StatusName {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
export abstract class Status {
static readonly ACTIVE = StatusName.ACTIVE
static readonly DEACTIVE = StatusName.DEACTIVE
static toDisplayName(status: StatusName) {...}
}
这样你在导入 Status 时会有很好的自动完成,但是会使用 IntelliSense 显示一些不必要的道具 Status.
P.S.
也许您的 toDisplayName
函数可以稍微优化一下,以防止在添加新状态时进行一些额外的工作
如果需要大写状态名,可以在helpers或者utils中声明大写函数
// helpers/capitalize.ts
export const capitalize = (str: string) => {
const firstLetter = str.charAt(0).toLocaleUpperCase();
const rest = str.slice(1).toLocaleLowerCase();
return firstLetter.concat(rest);
}
// Status.ts
export const toDisplayName = (status: StatusName) => capitalize(status);
我正在做 angular 项目,所以我们在这里使用打字稿。
我有一个状态枚举
export enum Status {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
这里的 properties/fields 是重复的,因为它在 serialization/deserialization 中有帮助,如果没有 Status.ACTIVE
就变成 0
的顺序。
现在为了显示目的,我们需要映射可表达的词,比如,
'ACTIVE'-> 'Active'
.
为此我们使用了命名空间,
export namespace Status {
export function displayName(s: Status){
const mapping = {Status.ACTIVE: 'Active', ...}; // I know this can declared at some other places so we don't need to re-initialize every time this function is called.
return mapping[s];
}
}
这使得 Status
的使用变得非常简单。因为现在我可以拥有 Status.ACTIVE
以及 Status.displayName(s)
。基本上使用相同的“classname”状态。 (当然两者都在 status.ts 文件中定义)
现在由于默认 lint 建议删除命名空间。
'namespace' and 'module' are disallowed (no-namespace)
我了解到命名空间是在 ES6 模块系统尚未到位时创建的。所以现在 classes 比名称空间更有意义。但就我而言 - 枚举的上下文
问题是,
- 命名空间的使用是否会产生任何性能、优化或任何其他问题?
- 有没有更好的方法来完成同样的事情(使用相同的“class”名称)
- 不创建命名空间并导出另一个以相同方式工作的函数 - 在同一个文件中运行但没有命名空间;那是解决方案吗?并且基本上不满足我最初要求具有相同 class 名称的要求。
喜欢关注
status.ts
export Status {
ACTIVE = 'ACTIVE'
}
export function statusToDisplayName(s: Status){
const map = {...};
return map[s];
}
usage.ts
import {Status, statusToDisplayName} from 'some/path/status';
...
status = Status.ACTIVE;
statusToDisplay = statusToDisplayName(status);
命名空间与 ES 模块
命名空间被认为已弃用,取而代之的是 ES 模块。它不会导致任何性能或优化问题,但在与 ES 模块一起使用时肯定会造成一些混乱。
作为命名空间的 ES 模块
您可以使用 ES 模块作为命名空间来实现类似的结果
// Status.ts
export enum Status {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
export function toDisplayName(s: Status){
const map = {...};
return map[s];
}
// some-other-module.ts
import * as StatusModule from './Status.ts'
const active = StatusModule.Status.ACTIVE;
const displayname = StatusModule.toDisplayName(active);
如果您希望状态为 'on the same level' 且具有 toDisplayName
功能,您可以考虑以下选项
// Status.ts
enum Status {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
export const ACTIVE = Status.ACTIVE;
export const DEACTIVE = Status.DEACTIVE;
export function toDisplayName(...){...}
但我不推荐,因为会导致代码重复
备选
为了保持所需的结构,您可以尝试使用静态道具class声明一个
// Status.ts
enum StatusName {
ACTIVE = 'ACTIVE',
DEACTIVE = 'DEACTIVE'
}
export abstract class Status {
static readonly ACTIVE = StatusName.ACTIVE
static readonly DEACTIVE = StatusName.DEACTIVE
static toDisplayName(status: StatusName) {...}
}
这样你在导入 Status 时会有很好的自动完成,但是会使用 IntelliSense 显示一些不必要的道具 Status.
P.S.
也许您的 toDisplayName
函数可以稍微优化一下,以防止在添加新状态时进行一些额外的工作
如果需要大写状态名,可以在helpers或者utils中声明大写函数
// helpers/capitalize.ts
export const capitalize = (str: string) => {
const firstLetter = str.charAt(0).toLocaleUpperCase();
const rest = str.slice(1).toLocaleLowerCase();
return firstLetter.concat(rest);
}
// Status.ts
export const toDisplayName = (status: StatusName) => capitalize(status);