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 的 getset 属性会产生错误。

有没有办法遵循样式指南并使用 TypeScript 的 get/set 属性?

【问题讨论】:

不幸的是,以最佳实践为中心的问题并不适合 Stack Overflow,因为它们主要会产生基于意见的答案(“我喜欢这样做......”,“人们通常使用这个...... 。”)。虽然您可能会根据作者认为的“最佳实践”看到其他问题的答案,但专门询问它们是题外话。有关详细信息,请参阅help center。您可能希望从问题中删除偏离主题的部分,而只关注技术问题。 不,the compiler doesn't complain。你的例子是有效的。 对不起,我更新了我的问题,我错过了一些实际上导致错误的代码。 你不能拥有它,因为它们最终都作为同一个 js 对象的属性。 在您的情况下,您可以将 get id() / set id(val) 替换为简单的实例变量 id,声明为公共。更易于阅读和书写,性能更高。 【参考方案1】:

回答

如果你想使用getset 访问器,你必须在私有属性前加上下划线。在所有其他情况下不要使用它。我想说在访问器中使用下划线是一种特殊情况,虽然它没有明确写在Coding guidelines 中,但这并不意味着它是错误的。他们在official documentation 中使用它。

下划线的原因

首先,我想强调fieldproperty 之间的区别。在标准的高级 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中类的使用详解

TypeScript中类的使用

Typescript(真的)是不是遵循泛型中参数化类型(T、U、V、W)的命名约定?

如果xml元素命名约定与POJO属性命名约定不同,则发送到Spring Boot REST API的XML元素不会映射到POJO

java中的类名约定[关闭]

如果 xml 元素命名约定与 POJO 属性命名约定不同,则发送到 Spring Boot REST API 的 XML 元素不会映射到 POJO