TypeScript 中类属性的命名约定
Posted
技术标签:
【中文标题】TypeScript 中类属性的命名约定【英文标题】:Naming convention for class properties in TypeScript 【发布时间】:2017-03-28 00:56:00 【问题描述】:根据offical style guide你应该
避免在私有属性和方法前加上下划线。
由于我来自 Java 背景,我通常只会使用 this
关键字:
export default class Device
private id: string;
constructor(id: string)
this.id = id;
public get id(): string // [ts] Duplicate identifier 'id'.
return this.id;
public set id(value: string) // [ts] Duplicate identifier 'id'.
this.id = value;
但 TypeScript 编译器抱怨:[ts] Duplicate identifier 'id'.
TypeScript 构造函数中的参数命名是否有约定或最佳实践?
使用 TypeScript 的 get 和 set 属性会产生错误。
有没有办法遵循样式指南并使用 TypeScript 的 get/set 属性?
【问题讨论】:
不幸的是,以最佳实践为中心的问题并不适合 Stack Overflow,因为它们主要会产生基于意见的答案(“我喜欢这样做......”,“人们通常使用这个...... 。”)。虽然您可能会根据作者认为的“最佳实践”看到其他问题的答案,但专门询问它们是题外话。有关详细信息,请参阅help center。您可能希望从问题中删除偏离主题的部分,而只关注技术问题。 不,the compiler doesn't complain。你的例子是有效的。 对不起,我更新了我的问题,我错过了一些实际上导致错误的代码。 你不能拥有它,因为它们最终都作为同一个 js 对象的属性。 在您的情况下,您可以将get id()
/ set id(val)
替换为简单的实例变量 id
,声明为公共。更易于阅读和书写,性能更高。
【参考方案1】:
回答
如果你想使用get
和set
访问器,你必须在私有属性前加上下划线。在所有其他情况下不要使用它。我想说在访问器中使用下划线是一种特殊情况,虽然它没有明确写在Coding guidelines 中,但这并不意味着它是错误的。他们在official documentation 中使用它。
下划线的原因
首先,我想强调field
和property
之间的区别。在标准的高级 OOP 语言(如 Java 或 C#)中,字段是私有成员,其他类不应该看到。如果你想在封装的情况下公开它,你应该创建一个属性。
在 Java 中,您可以这样做(称为 Bean 属性):
private int id;
public int getId()
return this.id;
public setId(int value)
this.id = value;
然后您可以通过调用这些方法来访问该属性:
int i = device.getId();
device.setId(i);
//increment id by 1
device.setId(device.getId() + 1);
另一方面,C# 被设计成更容易使用属性:
private int id;
public int Id
get
return this.id;
set
this.id = value;
(值始终是分配的值。)
您可以直接为这些属性赋值或获取属性值。
int i = device.Id;
device.Id = i;
//increment id by 1
device.Id++;
在纯 javascript 中,没有真正的字段,因为类成员始终是公共的;我们简单地称它们为属性。
在 TypeScript 中,您可以定义“真正的”类似 C# 的属性(带有封装)。为此,您使用Accessors。
private _id: number;
public get id(): number
return this._id;
public set id(value: number)
this._id = value;
用法:
let i: number = device.id;
device.id = i;
//increment id by 1
device.id++;
您必须在此处使用下划线,原因有两个:
-
在 JavaScript 中,所有类成员都是公共的。因此,通过在私有属性前加下划线,我们表示该属性(字段)是私有的,只能通过其公共属性访问。
如果您将私有属性和公共属性命名为相同的名称,JavaScript 解释器将不知道是访问私有属性还是公共属性。因此,您会收到您所写的错误:[ts] Duplicate identifier 'id'。
【讨论】:
【参考方案2】:如果问题是严格的:
有没有办法遵循 [typeScript] 样式指南并使用 get/set TypeScript 的属性?
TypeScript 样式指南所说的:
避免在私有属性和方法前加上下划线。
然后您可以使用$
(美元符号)而不是_
(下划线)来为您的私有字段添加前缀。通过这种方式,您既可以摆脱 [ts] Duplicate identifier 'blablabla'
错误,同时仍然遵守 TypeScript 样式指南。
此外,这只是我的看法,.$
combination 比 ._
combination 更具可读性。
【讨论】:
这是错误的。美元前缀通常用于可观察对象。 “这些指南适用于 TypeScript 项目代码库的贡献者。这不是 TypeScript 社区的规定性指南。” github.com/Microsoft/TypeScript/wiki/Coding-guidelines “美元前缀通常用于 observables”——这不是真的。对于 observables,通常使用美元 suffix。但我同意使用美元前缀而不是下划线前缀是没有意义的。两者都是邪恶的,但下划线的邪恶程度较小,因为它通常用于将财产标记为私有。这几乎是“标准”。 $ 用于 RxJS 中的 observables。不要这样做 _有什么不好的?【参考方案3】:对于属性访问器,您使用_
。
查看来自 Microsoft https://www.typescriptlang.org/docs/handbook/classes.html#accessors 的示例:
const fullNameMaxLength = 10;
class Employee
private _fullName: string;
get fullName(): string
return this._fullName;
set fullName(newName: string)
if (newName && newName.length > fullNameMaxLength)
throw new Error("fullName has a max length of " + fullNameMaxLength);
this._fullName = newName;
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName)
console.log(employee.fullName);
【讨论】:
以上是关于TypeScript 中类属性的命名约定的主要内容,如果未能解决你的问题,请参考以下文章
Typescript(真的)是不是遵循泛型中参数化类型(T、U、V、W)的命名约定?
如果xml元素命名约定与POJO属性命名约定不同,则发送到Spring Boot REST API的XML元素不会映射到POJO
如果 xml 元素命名约定与 POJO 属性命名约定不同,则发送到 Spring Boot REST API 的 XML 元素不会映射到 POJO