TypeScript Style Guide

微软官方规则

From Microsoft

Coding guidelines

While these guidelines are mainly meant for contributors to the TypeScript project, certain suggestions apply as to how idiomatic TypeScript code should be written (e.g. the "Names" and "Style" sections).

Names

  1. Use PascalCase for type names.
  2. Do not use "I" as a prefix for interface names.
  3. Use PascalCase for enum values.
  4. Use camelCase for function names.
  5. Use camelCase for property names and local variables.
  6. Do not use "_" as a prefix for private properties.
  7. Use whole words in names when possible.

Components

  1. 1 file per logical component (e.g. parser, scanner, emitter, checker).
  2. Do not add new files. :)
  3. files with ".generated.*" suffix are auto-generated, do not hand-edit them.

Types

  1. Do not export types/functions unless you need to share it across multiple components.
  2. Do not introduce new types/values to the global namespace.
  3. Shared types should be defined in 'types.ts'.
  4. Within a file, type definitions should come first.

null and undefined

  1. Use undefined, do not use null.

General Assumptions

  1. Consider objects like Nodes, Symbols, etc. as immutable outside the component that created them. Do not change them.
  2. Consider arrays as immutable by default after creation.

Classes

  1. For consistency, do not use classes in the core compiler pipeline. Use function closures instead.

Flags

  1. More than 2 related Boolean properties on a type should be turned into a flag.

Comments

  1. Use JSDoc style comments for functions, interfaces, enums, and classes.

Strings

  1. Use double quotes for strings.
  2. All strings visible to the user need to be localized (make an entry in diagnosticMessages.json).

Diagnostic Messages

  1. Use a period at the end of a sentence.
  2. Use indefinite articles for indefinite entities.
  3. Definite entities should be named (this is for a variable name, type name, etc..).
  4. When stating a rule, the subject should be in the singular (e.g. "An external module cannot..." instead of "External modules cannot...").
  5. Use present tense.

Diagnostic Message Codes

Diagnostics are categorized into general ranges. If adding a new diagnostic message, use the first integral number greater than the last used number in the appropriate range.
* 1000 range for syntactic messages * 2000 for semantic messages * 4000 for declaration emit messages * 5000 for compiler options messages * 6000 for command line compiler messages * 7000 for noImplicitAny messages

General Constructs

For a variety of reasons, we avoid certain constructs, and use some of our own. Among them:

  1. Do not use ECMAScript 5 functions; instead use those found in core.ts.
  2. Do not use for..in statements; instead, use ts.forEach, ts.forEachKey and ts.forEachValue. Be aware of their slightly different semantics.
  3. Try to use ts.forEach, ts.map, and ts.filter instead of loops when it is not strongly inconvenient.

Style

  1. Use arrow functions over anonymous function expressions.
  2. Only surround arrow function parameters when necessary.
    For example, (x) => x + x is wrong but the following are correct:
    1. x => x + x
    2. (x,y) => x + y
    3. <T>(x: T, y: T) => x === y
  3. Always surround loop and conditional bodies with curly braces.
  4. Open curly braces always go on the same line as whatever necessitates them.
  5. Parenthesized constructs should have no surrounding whitespace.
    A single space follows commas, colons, and semicolons in those constructs. For example:
    1. for (var i = 0, n = str.length; i < 10; i++) { }
    2. if (x < 10) { }
    3. function f(x: number, y: string): void { }
  6. Use a single declaration per variable statement
    (i.e. use var x = 1; var y = 2; over var x = 1, y = 2;).
  7. else goes on a separate line from the closing curly brace.

网友整理

https://github.com/Platypi/style_typescript

TypeScript Style Guide

This is the TypeScript style guide that we use internally at Platypi! It is semi-reasonable, but it's more important that we keep a consistent look/feel of our code.

Table of Contents

  1. Introduction
  2. Browser Compatibility
  3. Files
  4. Indentation
  5. Line Length
  6. Quotes
  7. Comments
    1. Class
    2. Inline
    3. Todo and XXX
  8. Variable Declarations
  9. Function Declarations
    1. Anonymous Functions
  10. Names
    1. Variables, Modules, and Functions
    2. Types
    3. Classes
    4. Interfaces
    5. Constants
  11. Statements
    1. Simple
    2. Compound
    3. Return
    4. If
    5. For
    6. While
    7. Do While
    8. Switch
    9. Try
    10. Continue
    11. Throw
  12. Whitespace
  13. Object and Array Literals
  14. Assignment Expressions
  15. = and ! Operators
  16. Eval
  17. TSLint
  18. License

Introduction

When developing software as an organization, the value of the software produced is directly affected by the quality of the codebase. Consider a project that is developed over many years and handled/seen by many different people. If the project uses a consistent coding convention it is easier for new developers to read, preventing a lot of time/frustration spent figuring out the structure and characteristics of the code. For that purpose, we need to make sure we adhere to the same coding conventions across all of our products. This will not only help new developers, but it will also aid in quickly identifying potential flaws in the code, thereby reducing the brittleness of the code.

Browser Compatibility

  • Target modern browsers ie >= 9

Files

  • All TypeScript files must have a ".ts" extension.
  • They should be all lower case, and only include letters, numbers, and periods.
  • It is OK (even recommended) to separate words with periods (e.g. my.view.html).
  • All files should end in a new line. This is necessary for some Unix systems.

Indentation

  • The unit of indentation is four spaces.
  • Never use tabs, as this can lead to trouble when opening files in different IDEs/Text editors. Most text editors have a configuration option to change tabs to spaces.

Line Length

  • Lines must not be longer than 140 characters.
  • When a statement runs over 140 characters on a line, it should be broken up, ideally after a comma or operator.

Quotes

  • Use single-quotes '' for all strings, and use double-quotes "" for strings within strings.
  // bad
  var greeting = "Hello World!";
  // good
  var greeting = 'Hello World!';
  // bad
  var html = "<div class='bold'>Hello World</div>";
  // bad
  var html = '<div class=\'bold\'>Hello World</div>';
  // good
  var html = '<div class="bold">Hello World</div>';

Comments

  • Comments are strongly encouraged. It is very useful to be able to read comments and understand the intentions of a given block of code.
  • Comments need to be clear, just like the code they are annotating.
  • Make sure your comments are meaningful.

The following example is a case where a comment is completely erroneous, and can actually make the code harder to read.

  // Set index to zero.
  var index = 0;
  • All public functions must have a comment block /**...*/ using JSDoc style comments.

JSDocs can be interpreted by IDEs for better intellisense. Below is an example of a JSDoc comment block for a function.

  /**
   * Takes in a name and returns a greeting string.
   * 
   * @param name The name of the greeted person.
   */
  function getGreeting(name: string): string {
      return 'Hello ' + name + '!';
  }

Class

  • All classes must have block comments /**...*/ for all public variables and functions.
  • All public functions should use JSDoc style comments.
  • Functions need to have a comment explaining what the function does, and all of the input parameters need to be annotated with @param.
  • The class should include a block comment containing the description of the class
  • The constructor should contain a JSDoc comment annotating any input parameters.
  /**
   * Contains properties of a Person.
   */
  class Person {
      /**
       * Returns a new Person with the specified name.
       * 
       * @param name The name of the new Person.
       */
      static GetPerson(name: string): Person {
          return new Person(name);
      }
      /**
       * @param name The name of the new Person.
       */
      constructor(public name: string) { }
      /**
       * Instructs this Person to walk for a certain amount 
       * of time.
       *
       * @param millis The number of milliseconds the Person 
       * should walk.
       */
      walkFor(millis: number) {
          console.log(this.name + ' is now walking.');
          setTimeout(() => {
              console.log(this.name + ' has stopped walking.');
          }, millis);
      }
  }

Inline

  • Inline comments are comments inside of complex statements (loops, functions, etc).
  • Use // for all inline comments.
  • Keep comments clear and concise.
  • Place inline comments on a newline above the line they are annotating
  • Put an empty line before the comment.
  // bad
  var lines: Array<string>; // Holds all the lines in the file.
  // good
  // Holds all the lines in the file.
  var lines: Array<string>;
  // bad
  function walkFor(name: string, millis: number) {
      console.log(name + ' is now walking.');
      // Wait for millis milliseconds to stop walking
      setTimeout(() => {
          console.log(name + ' has stopped walking.');
      }, millis);
  }
  // good
  function walkFor(name: string, millis: number) {
      console.log(name + ' is now walking.');
      // Wait for millis milliseconds to stop walking
      setTimeout(() => {
          console.log(name + ' has stopped walking.');
      }, millis);
  }

Todo and XXX

TODO and XXX annotations help you quickly find things that need to be fixed/implemented.

  • Use // TODO: to annotate solutions that need to be implemented.
  • Use // XXX: to annotate problems the need to be fixed.
  • It is best to write code that doesn't need TODO and XXX annotations, but sometimes it is unavoidable.

Variable Declarations

  • All variables must be declared prior to using them. This aids in code readability and helps prevent undeclared variables from being hoisted onto the global scope.
  // bad
  console.log(a + b);
  var a = 2,
      b = 4;
  // good
  var a = 2,
      b = 4;
  console.log(a + b);
  • Implied global variables should never be used.
  • You should never define a variable on the global scope from within a smaller scope.
  // bad
  function add(a: number, b: number) {
      // c is on the global scope!
      c = 6;
      return a + b + c;
  }
  • Use one var keyword to define a block of variables.
  • Declare each variable on a newline.
  // bad
  var a = 2;
  var b = 2;
  var c = 4;
  // good
  var a = 2,
      b = 2,
      c = 4;
  // bad
  // b will be defined on global scope.
  var a = b = 2, c = 4;

Function Declarations

  • All functions must be declared before they are used.
  • Any closure functions should be defined right after the var declarations.
  // bad
  function createGreeting(name: string): string {
      var message = 'Hello ';
      return greet;
      function greet() {
          return message + name + '!';
      }
  }
  // good
  function createGreeting(name: string): string {
      var message = 'Hello ';
      function greet() {
          return message + name + '!';
      }
      return greet;
  }
  • There should be no space between the name of the function and the left parenthesis ( of its parameter list.
  • There should be one space between the right parenthesis ) and the left curly { brace that begins the statement body.
  // bad
  function foo (){
      // ...
  }
  // good
  function foo() {
      // ...
  }
  • The body of the function should be indented 4 spaces.
  • The right curly brace } should be on a new line.
  • The right curly brace } should be aligned with the line containing the left curly brace { that begins the function statement.
  // bad
  function foo(): string {
    return 'foo';}
  // good
  function foo(): string {
      return 'foo';
  }
  • For each function parameter
    • There should be no space between the parameter and the colon : indicating the type declaration.
    • There should be a space between the colon : and the type declaration.
  // bad
  function greet(name:string) {
    // ...
  }
  // good
  function greet(name: string) {
    // ...
  }

Anonymous Functions

  • All anonymous functions should be defined as fat-arrow/lambda () => { } functions unless it is absolutely necessary to preserve the context in the function body.
  • All fat-arrow/lambda functions should have parenthesis () around the function parameters.
  // bad
  clickAlert() {
      var element = document.querySelector('div');
      this.foo = 'foo';
      element.addEventListener('click', function(ev: Event) {
          // this.foo does not exist!
          alert(this.foo);
      });
  }
  // good
  clickAlert() {
      var element = document.querySelector('div');
      this.foo = 'foo';
      element.addEventListener('click', (ev: Event) => {
          // TypeScript allows this.foo to exist!
          alert(this.foo);
      });
  }
  • There should be a space between the right parenthesis ) and the =>
  • There should be a space between the => and the left curly brace { that begins the statement body.
  // bad
  element.addEventListener('click', (ev: Event)=>{alert('foo');});
  // good
  element.addEventListener('click', (ev: Event) => {
      alert('foo');
  });
  • The statement body should be indented 4 spaces.
  • The right curly brace } should be on a new line.
  • The right curly brace } should be aligned with the line containing the left curly brace { that begins the function statement.

Names

  • All variable and function names should be formed with alphanumeric A-Z, a-z, 0-9 and underscore _ charcters.

Variables, Modules, and Functions

  • Variable, module, and function names should use lowerCamelCase.

Types

  • Types should be used whenever necessary.
  • Arrays should be defined as Array<type> instead of type[].
  • Use the any type sparingly, it is always better to define an interface.
  • Always define the return type of functions.
  • If TypeScript is capable of implicitly determining the return type of a function, then it is unnecessary to define the return type.
  • Always define the types of variables/parameters unless TypeScript can implicitly infer their type.
  // bad
  var numbers = [];
  // bad
  var numbers: number[] = [];
  // good
  var numbers: Array<number> = [];

Classes

  • Classes/Constructors should use UpperCamelCase (PascalCase).
  • Private and private static members in classes should be denoted with the private keyword.
  • Private and private static members should be prefaced with 2 underscores __.
  • Protected members in classes do not use the private keyword.
  • Protected members in classes should be prefaced with 1 underscore _.
  class Person {
      private __fullName: string;
      constructor(public firstName: string, public lastName: string) {
          this.__fullName = firstName + ' ' + lastName;
      }
      _walkFor(millis: number) {
          console.log(this.__fullName + ' is now walking.');
          // Wait for millis milliseconds to stop walking
          setTimeout(() => {
              console.log(this.__fullName + ' has stopped walking.');
          }, millis);
      }
      toString() {
          return this.__fullName;
      }
  }

Interfaces

  • Interfaces should use UpperCamelCase.
  • Interfaces should be prefaced with the capital letter I.
  • Only public members should be in an interface, leave out protected and private members.
  interface IPerson {
      firstName: string;
      lastName: string;
      toString(): string;
  }

Constants

  • All constants should use UPPERSNAKECASE.

Statements

Simple

  • Each line should contain at most one statement.
  • A semicolon should be placed at the end of every simple statement.
  // bad
  var greeting = 'Hello World'
  alert(greeting)
  // good
  var greeting = 'Hello World';
  alert(greeting);

Compound

Compound statements are statements containing lists of statements enclosed in curly braces {}.

  • The enclosed statements should start on a newline.
  • The enclosed statements should be indented 4 spaces.
  // bad
  if (condition === true) { alert('Passed!'); }
  // good
  if (condition === true) { 
      alert('Passed!'); 
  }
  • The left curly brace { should be at the end of the line that begins the compound statement.
  • The right curly brace } should begin a line and be indented to align with the line containing the left curly brace {.
  // bad
  if (condition === true)
  { 
      alert('Passed!');
  }
  // good
  if (condition === true) {
      alert('Passed!');
  }
  • Braces {} must be used around all compound statements even if they are only single-line statements.
  // bad
  if (condition === true) alert('Passed!');
  // bad
  if (condition === true)
      alert('Passed!');
  // good
  if (condition === true) {
      alert('Passed!');
  }

If you do not add braces {} around compound statements, it makes it very easy to accidentally introduce bugs.

  if (condition === true)
      alert('Passed!');
      return condition;

It appears the intention of the above code is to return if condition === true, but without braces {} the return statement will be executed regardless of the condition.

  • Compount statements do not need to end in a semicolon ; with the exception of a do { } while(); statement.

Return

  • If a return statement has a value you should not use parenthesis () around the value.
  • The return value expression must start on the same line as the return keyword.
  // bad
  return 
      'Hello World!';
  // bad
  return ('Hello World!');
  // good
  return 'Hello World!';
  • It is recommended to take a return-first approach whenever possible.
  // bad
  function getHighestNumber(a: number, b: number): number {
      var out = b;
      if(a >= b) {
          out = a;
      }
      return out;
  }
  // good
  function getHighestNumber(a: number, b: number): number {
      if(a >= b) {
          return a;
      }
      return b;
  }
  • Always explicitly define a return type. This can help TypeScript validate that you are always returning something that matches the correct type.
  // bad
  function getPerson(name: string) {
      return new Person(name);
  }
  // good
  function getPerson(name: string): Person {
      return new Person(name);
  }

If

  • Alway be explicit in your if statement conditions.
  // bad
  function isString(str: any) {
      return !!str;
  }
  // good
  function isString(str: any) {
      return typeof str === 'string';
  }

Sometimes simply checking falsy/truthy values is fine, but the general approach is to be explicit with what you are looking for. This can prevent a lot of unncessary bugs.

If statements should take the following form:

  if (/* condition */) {
      // ...
  }
  if (/* condition */) {
      // ...
  } else {
      // ...
  }
  if (/* condition */) {
      // ...
  } else if (/* condition */) {
      // ...
  } else {
      // ...
  }

For

For statements should have the following form:

  for(/* initialization */; /* condition */; /* update */) {
      // ...
  }
  var keys = Object.keys(/* object */),
      length = keys.length;
  for(var i = 0; i < length; ++i) {
      // ...
  }

Object.prototype.keys is supported in ie >= 9.

  • Use Object.prototype.keys in lieu of a for...in statement.

While

While statements should have the following form:

  while (/* condition */) {
      // ...
  }

Do While

  • Do while statements should be avoided unless absolutely necessary to maintain consistency.
  • Do while statements must end with a semicolon ;

Do while statements should have to following form:

  do {
      // ...
  } while (/* condition */);

Switch

Switch statements should have the following form:

  switch (/* expression */) {
      case /* expression */:
          // ...
          /* termination */
      default:
          // ...
  }
  • Each switch group except default should end with break, return, or throw.

Try

  • Try statements should be avoided whenever possible. They are not a good way of providing flow control.

Try statements should have the following form:

  try {
      // ...
  } catch (error: Error) {
      // ...
  }
  try {
      // ...
  } catch (error: Error) {
      // ...
  } finally {
      // ...
  }

Continue

  • It is recommended to take a continue-first approach in all loops.

Throw

  • Avoid the use of the throw statement unless absolutely necessary.
  • Flow control through try/catch exception handling is not recommended.

Whitespace

Blank lines improve code readability by allowing the developer to logically group code blocks. Blank spaces should be used in the following circumstances.

  • A keyword followed by left parenthesis ( should be separated by 1 space.
  // bad
  if(condition) {
      // ...
  }
  // good
  if (condition) {
      // ...
  }
  • All operators except for period ., left parenthesis (, and left bracket [ should be separated from their operands by a space.
  // bad
  var sum = a+b;
  // good
  var sum = a + b;
  // bad
  var name = person . name;
  // good
  var name = person.name;
  // bad
  var item = items [4];
  // good
  var item = items[4];
  • No space should separate a unary/incremental operator !x, -x, +x, ~x, ++x, --x and its operand.
  // bad
  var neg = - a;
  // good
  var neg = -a;
  • Each semicolon ; in the control part of a for statement should be followed with a space.
  // bad
  for(var i = 0;i < 10;++i) {
      // ...
  }
  // good
  for(var i = 0; i < 10; ++i) {
      // ...
  }

Object and Array Literals

  • Use curly braces {} instead of new Object().
  • Use brackets [] instead of new Array().

Assignment Expressions

  • Assignment expressions inside of the condition block of if, while, and do while statements should be avoided.
  // bad
  while (node = node.next) {
      // ...
  }
  // good
  while (typeof node === 'object') {
      node = node.next;
      // ...
  }

= and ! Operators

  • It is better to use === and !== operators whenever possible.
  • == and != operators do type coercion, which can lead to headaches when debugging code.

Eval

  • Never use eval
  • Never use the Function constructor
  • Never pass strings to setTimeout or setInterval

TSLint

  • Always use a Linter

Linting your code is very helpful for preventing minor issues that can escape the eye during development. We use TSLint (written by Palantir) for our linter.

License

(The MIT License)

Copyright (c) 2014 Platypi, LLC

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Richard Qiu

Life is a gift ! I love waking up in the moring and not konowing what's going to hanppen,or who I'm going to meeting,where I'm going to wind up. so, keep optimistic and enjoy life!

Shanghai