mirror of
				https://github.com/NativeScript/NativeScript.git
				synced 2025-11-01 01:19:52 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			550 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			550 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # NativeScript Modules Coding Convention
 | |
| 
 | |
| ## Tabs vs Spaces
 | |
| 
 | |
| Use tab width 2 indentation.
 | |
| 
 | |
| ## Line length
 | |
| 
 | |
| Try to limit your lines to 600 characters.
 | |
| 
 | |
| ## Semicolons, statement Termination
 | |
| 
 | |
| Always use semicolons where it is appropriate.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| let x = 1;
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let x = 1
 | |
| ```
 | |
| 
 | |
| ## Quotes
 | |
| 
 | |
| Use single quotes for strings:
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| let foo = 'bar';
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let foo = "bar";
 | |
| ```
 | |
| 
 | |
| ## Braces
 | |
| 
 | |
| Your opening braces go on the same line as the statement.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| if (true) {
 | |
|   console.log('winning');
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| if (true)
 | |
| {
 | |
|   console.log('losing');
 | |
| }
 | |
| ```
 | |
| 
 | |
| Also, notice the use of whitespace before and after the condition statement.
 | |
| 
 | |
| Follow the JavaScript convention of stacking `else/catch` clauses on the same line as the previous closing brace.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| if (i % 2 === 0) {
 | |
|   console.log('even');
 | |
| } else {
 | |
|   console.log('odd');
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| if (i % 2 === 0) {
 | |
|   console.log('even');
 | |
| }
 | |
| else {
 | |
|   console.log('odd');
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Variable declarations
 | |
| 
 | |
| Declare variables with `let` instead of `var`. Use `const` when possible.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| const button = new Button();
 | |
| 
 | |
| for (let i = 0; i < items.length; i++) {
 | |
|   // do something
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| var button = new Button();
 | |
| 
 | |
| for (var i = 0; i < items.length; i++) {
 | |
|   // do something
 | |
| }
 | |
| 
 | |
| ```
 | |
| 
 | |
| ## Variable and property names
 | |
| 
 | |
| Variables and properties should use [lower camel case][camelcase]
 | |
| capitalization. They should also be descriptive. Single character variables and
 | |
| uncommon abbreviations should generally be avoided unless it is something well known as **i** in for loops
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| let adminUser = db.query('SELECT * FROM users ...');
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let admin_user = db.query('SELECT * FROM users ...');
 | |
| ```
 | |
| 
 | |
| [camelcase]: https://en.wikipedia.org/wiki/camelCase#Variations_and_synonyms
 | |
| 
 | |
| ## Type names
 | |
| 
 | |
| Type names should be capitalized using [upper camel case][camelcase].
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| class UserAccount() {
 | |
|   this.field = 'a';
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| class userAccount() {
 | |
|   this.field = 'a';
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Constants
 | |
| 
 | |
| Constants should be declared with CAPITAL letters and `const` keyword. Use underscore to name constants with complex wording.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| const SECOND = 1 * 1000;
 | |
| const MY_SECOND = SECOND;
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| var second = 1 * 1000;
 | |
| ```
 | |
| 
 | |
| ## Object / Array creation
 | |
| 
 | |
| Use trailing commas and put *short* declarations on a single line. Only quote
 | |
| keys when your interpreter complains:
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| let a = ['hello', 'world'];
 | |
| let b = {
 | |
|   good: 'code',
 | |
|   'is generally': 'pretty',
 | |
| };
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let a = [
 | |
|   'hello', 'world'
 | |
| ];
 | |
| let b = {'good': 'code'
 | |
|         , is generally: 'pretty'
 | |
|         };
 | |
| ```
 | |
| 
 | |
| ## Equality operator
 | |
| 
 | |
| Use the [strict comparison operators][comparisonoperators] when needed. The triple equality operator helps to maintain data type integrity throughout the code.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| let a = 0;
 | |
| if (a === '') {
 | |
|   console.log('winning');
 | |
| }
 | |
| 
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let a = 0;
 | |
| if (a == '') {
 | |
|   console.log('losing');
 | |
| }
 | |
| ```
 | |
| 
 | |
| [comparisonoperators]: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comparison_Operators
 | |
| 
 | |
| ## Short-hand operators
 | |
| 
 | |
| Try to avoid short-hand operators except in very simple scenarios.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| let default = x || 50;
 | |
| let extraLarge = 'xxl';
 | |
| let small = 's'
 | |
| let big = (x > 10) ? extraLarge : small;
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let default = checkX(x) || getDefaultSize();
 | |
| let big = (x > 10) ? checkX(x) ? getExtraLarge() : getDefaultSize() : getSmallValue();
 | |
| ```
 | |
| 
 | |
| ## Curly braces 
 | |
| 
 | |
| Always use curly braces even in the cases of one line conditional operations.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| if (a) {
 | |
|   return 'winning';
 | |
| }
 | |
| 
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| 
 | |
| if (a)
 | |
|   return 'winning';
 | |
| 
 | |
| if (a) return 'winning';
 | |
| ```
 | |
| 
 | |
| ## Boolean comparisons
 | |
| 
 | |
| **Do not** directly compare with `true` or `false`.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| 
 | |
| if (condition) {
 | |
|   console.log('winning');
 | |
| }
 | |
| 
 | |
| if (!condition) {
 | |
|   console.log('winning');
 | |
| }
 | |
| 
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| 
 | |
| if (condition === true) {
 | |
|   console.log('losing');
 | |
| }
 | |
| 
 | |
| if (condition !== true) {
 | |
|   console.log('losing');
 | |
| }
 | |
| 
 | |
| if (condition !== false) {
 | |
|   console.log('losing');
 | |
| }
 | |
| 
 | |
| ```
 | |
| 
 | |
| ## Boolean conditions format
 | |
| Do not use the **Yoda Conditions** when writing boolean expressions:
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| let num;
 | |
| if (num >= 0) {
 | |
|   console.log('winning');
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let num;
 | |
| if (0 <= num) {
 | |
|   console.log('losing');
 | |
| }
 | |
| ```
 | |
| 
 | |
| **NOTE** It is OK to use constants on the left when comparing for a range.
 | |
| ```TypeScript
 | |
| if (0 <= num && num <= 100) {
 | |
|   console.log('winning');
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Function length
 | |
| Keep your functions short. A good function fits on a slide that the people in
 | |
| the last row of a big room can comfortably read. So don't count on them having
 | |
| perfect vision and limit yourself to 1/2 of your screen height per function (no screen rotation :).
 | |
| 
 | |
| ## Return statements
 | |
| There are a few important considerations here:
 | |
| + To avoid deep nesting of if-statements, always return a function's value as early
 | |
| as possible. In certain routines, once you know the answer, you want to return it to the calling routine immediately. If the routine is defined in such a way that it doesn't require any cleanup, not returning immediately means that you have to write more code.
 | |
| + Minimize the number of returns in each routine. It's harder to understand a routine if, reading it at the bottom, you're unaware of the possibility that it *return*ed somewhere above.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| function getSomething(val) {
 | |
|   if (val < 0) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   if (val > 100) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   let res1 = doOne();
 | |
|   let res2 = doTwo();
 | |
|   let options = {
 | |
|     a: 1,
 | |
|     b: 2
 | |
|   };
 | |
|   let result = doThree(res1, res2, options);
 | |
|   return result;
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| function getSomething(val) {
 | |
|   if (val >= 0) {
 | |
|     if (val < 100) {
 | |
|       let res1 = doOne();
 | |
|       let res2 = doTwo();
 | |
|       let options = {
 | |
|         a: 1,
 | |
|         b: 2
 | |
|       };
 | |
|       let result = doThree(res1, res2, options);
 | |
|       return result;
 | |
|     }
 | |
|     else {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   else {
 | |
|     return false;
 | |
|   }
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Arrow Functions
 | |
| 
 | |
| Use arrow functions over anonymous function expressions. Typescript will take care of `this`.
 | |
| 
 | |
| *Right:*
 | |
| 
 | |
| ```TypeScript
 | |
| req.on('end', () => {
 | |
|   exp1();
 | |
|   exp2();
 | |
|   this.doSomething();
 | |
| });
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| 
 | |
| ```TypeScript
 | |
| let that = this;
 | |
| req.on('end', function () {
 | |
|   exp1();
 | |
|   exp2();
 | |
|   that.doSomething();
 | |
| });
 | |
| ```
 | |
| 
 | |
| ## Comments
 | |
| 
 | |
| Use the [JSDoc][JSDOC] convention for comments. When writing a comment always think how understandable will be for somebody who is new to this code. Even if it may look simple to you think how a guy that just joined will understand it. Always comment in the following cases:
 | |
| + When there is some non-trivial logic.
 | |
| + Some "external" knowledge is needed which is missing in the context - workaround for a driver, module bug, special 'hack' because of a bug and so on;
 | |
| + When you are creating a new class
 | |
| + Public methods - include all the arguments and if possible the types {String}, {Number}. Optional arguments should be marked too. Check the [@param tag][param]
 | |
| 
 | |
| [JSDOC]: https://devdocs.io/jsdoc/
 | |
| [param]: https://devdocs.io/jsdoc/tags-param
 | |
| 
 | |
| ## File/module structure
 | |
| 
 | |
| A typical module should have the following structure:
 | |
| 
 | |
| 1. required dependencies
 | |
| 2. module-private declarations - variables, functions, classes, etc.
 | |
| 3. export variables and functions
 | |
| 4. export class declarations
 | |
| 
 | |
| <!--
 | |
| For more information see [this file](https://github.com/telerik/xPlatCore/blob/master/JS/BCL/CreateNewModule.md)
 | |
| -->
 | |
| 
 | |
| ## File naming
 | |
| Use lower case for file names. Use a dash to separate different words.
 | |
| 
 | |
| *Right:*
 | |
| file-system
 | |
| 
 | |
| *Wrong:*
 | |
| FileSystem, fileSystem, file_system
 | |
| 
 | |
| ## This, that, self
 | |
| When you **need** to keep a reference to **this** use **that** as the name of the variable. Additionally, if you use the TypeScript lambda support, the compiler will take care of this automatically.
 | |
| 
 | |
| *Right:*
 | |
| ```TypeScript
 | |
| let that = this;
 | |
| doSomething(function() {
 | |
|   that.doNothing();
 | |
| });
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| ```TypeScript
 | |
| let me = this;
 | |
| doSomething(function() {
 | |
|   me.doNothing();
 | |
| });
 | |
| ```
 | |
| 
 | |
| ## Private (hidden) variables and methods
 | |
| Although there is the **private** keyword in TypeScript, it is only a syntax sugar. There is no such notation in JavaScript and everything is available to the users. Hence, always use underscore (**_**) to prefix private variables and methods. There are also methods which have the **public** visibility but they are meant to be used within our code ONLY. Such methods should also be prefixed with an underscore.
 | |
| 
 | |
| *Right:*
 | |
| ```TypeScript
 | |
| class Foo {
 | |
|   private _myBoolean: boolean;
 | |
|   
 | |
|   public publicAPIMethod() {
 | |
|   }
 | |
|   
 | |
|   public _frameworkMethod() {
 | |
|       // this method is for internal use only
 | |
|   }
 | |
|   
 | |
|   private _doSomething() {
 | |
|   }
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| ```TypeScript
 | |
| class Foo {
 | |
|   private myBoolean: boolean;
 | |
|   
 | |
|   public _publicAPIMethod() {
 | |
|   }
 | |
|   
 | |
|   public frameworkMethod() {
 | |
|       // this method is for internal use only
 | |
|   }
 | |
|   
 | |
|   private doSomething() {
 | |
|   }
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## TypeScript optional parameters
 | |
| **Do not** use optional parameters in IMPLEMENTATION files. This is because the TS compiler generates additional array and populates it from the **arguments** object. Still, it is OK to use these in a definition file (as declarations ONLY).
 | |
| 
 | |
| *Right:*
 | |
| ```TypeScript
 | |
| // declaration
 | |
| export declare function concat(...categories: string[]): string;
 | |
| 
 | |
| // implementation
 | |
| export function concat(): string {
 | |
|   let i;
 | |
|   let result: string;
 | |
|   // use the arguments object to iterate the parameters
 | |
|   for (i = 0; i < arguments.length; i++) {
 | |
|     // do something
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| ```
 | |
| 
 | |
| *Wrong:*
 | |
| ```TypeScript
 | |
| // declaration
 | |
| export declare function concat(...categories: string[]): string;
 | |
| 
 | |
| // implementation
 | |
| export function concat(...categories: string[]): string {
 | |
|   let i;
 | |
|   let result: string;
 | |
|   // use the arguments object to iterate the parameters
 | |
|   for (i = 0; i < categories.length; i++) {
 | |
|     // do something
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Naming test functions
 | |
| Name your test function with `test_` so that our test runner can find them and add 'underscore' tested method/property name. Different words should be capitalized (and optionally separated by 'underscore').
 | |
| 
 | |
| *Right:*
 | |
| ```TypeScript
 | |
| export function test_goToVisualState_NoState_ShouldResetStyledProperties() {
 | |
|   // Test code here.
 | |
| }
 | |
| ```
 | 
