List of npm packages that help check code style in your project:
- jscs-preset-loris (use
eslint-config-loris
instead)
JavaScript and TypeScript Style Guide
License: Other
List of npm packages that help check code style in your project:
eslint-config-loris
instead)Good
import {foo, bar} from './foo';
Bad
import { foo, bar } from './foo';
Like in objects and destructuring assignment.
We have big discussions here. A good question is when we should stop and make a final decision.
Ideas? Suggestions?
===
operator possesses additional semantics in JavaScript. It means ‘compare variables values AND compare variables types’. Using it in situations when types cannot differ (like typeof a === 'string'
) is just overloading code with meaningless semantics.
Our rule there is as follows: if function allows polymorphic behavior, i.e. function arguments could be of different types, then all arguments MUST be explicitly cast at variables initialization block at the beginning of the function. That strictly eliminates any need of checking types below that block, and any type checking simply means that you were too lazy to cast types explicitly.
I suggest to change this rule: if you need to check types, do it explicitly at the beginning of function or code block.
Not everyone is so happy to be able to assume that global undefined
is untouched by user.
I suggest to change undefined
checking to typeof x == 'undefined'
since it's just safer.
«Операторы размещаются на предыдущей строке» — довольно тонкий момент.
Как в Яндексе принято писать чейнинг функций?
someVar
.method1
.method2
или
someVar.
method1.
method2
Ведь property accessor точно такой же оператор, как и конкатенация.
2.11.0
) #733.2.0
) #730.17.0
) #752.12.0
) #740.9.0
) #762.9.0
) #772.11.0
)2.9.0
) #692.0.0-alpha-1
) #701.0.0-rc-1
) #702.12.0
) #703.4.0
) #712.0.0-beta.1
) #732.11.0
) #732.0.0-beta.1
) #733.3.0
)es5
to es6
. #73Why using event names like-that
?
No major JS standard uses such naming.
Since Promises will be part of the language soon, we need rules to use them, like 'reject with Error instances'.
See #89 (comment)
Right now the codestyle neither approves nor forbides wrapping JS object into single line (like that: {prop1: value1, prop2: value2}
, though all ‘Good’ examples contain no such code. Shouldn't we explicitly state whether or not object wrapping is appropriate?
Why using this rule in 2014?
Are you still making one large js file with cat
?
There've been a discussion around our current naming rules for templates. @vmit suggests (IIUC) to adopt a rule that will allow to distinguish a template parameter in code.
The main concern is naming conflicts for constrained template parameters, i.e. the ones required to extend a type or implement a interface:
interface StyleExtractor<S extends Style> {
(...args: any[]): S;
}
Here's S
is a violation of our style guide. But it's difficult to come up with an alternative since the most sane one is Style
but it's already taken:( In this particular example we can rename Style
in import statement, but that's not a universal solution.
During discussion we've looked at some other codebases and code styles to gather more input. Here's the findings:
T
to name of a parameter (but the one for C++ doesn't);T
, U
, etc or TType
.TypeScript supports two forms of type assertions:
<any>foo;
as
operatorfoo as any;
From handbook:
The two samples are equivalent. Using one over the other is mostly a choice of preference; however, when using TypeScript with JSX, only as-style assertions are allowed.
Maybe we should add some rules for that. E.g. use "angle-bracket" syntax if you don't use JSX.
Use tslint's max-line-length instead of ter-max-len
It seems hard to support two files and keep them the same.
Current style does not allow easy chaining and makes it hard to visually see then/else branches when latter are longer then 20 symbols.
Long lines
(current codestyle)
var result = someLong || butNot || veryComplicated || condition ?
some + pretty + long + but + simple + expression :
fallback;
vs
(proposed)
var result = someLong || butNot || veryComplicated || condition
? some + pretty + long + but + simple + expression
: fallback;
?
and :
immediately attract attention.
Chaining
Chaining ternary operator is a nice feature for small inline multi-condition choosing:
(current coodestyle)
var value = /blah/.test(x) ?
'blah' :
/foo/.test(x) ?
'foo' :
/bar/.test(x) ?
'bar' :
'nope';
(proposed)
var value = /blah/.test(x) ? 'blah' :
/foo/.test(x) ? 'foo' :
/bar/.test(x) ? 'bar' :
'nope';
funcion Emitter() {
this._events = {};
}
function Child() {
Emitter.call(this);
// ...
}
Обязательно вызывать конструктор родителя в дочерних классах, даже если он пустой. Во-первых, если он вдруг станет не пустым, прийдётся перетрахать всех детей (добавляя этот вызов), во-вторых, не всегда вообще будет такая возможность, например, либа уже юзается в разных проектах, и вдруг в конструктор понадобилось что-то добавить. Если при этом дока либы не требовала такого вызова, то придётся извращаться в каждом методе как-то так:
Emitter.prototype.addListener = function(type, listener, context) {
var events = this._events || (this._events = {});
// ...
};
Хотя это может и так оказаться полезным, например, если класс должен иметь возможность использоваться как примесь, но в большинстве случаев это не удобно.
Ещё можно учесть, что иногда классы в js используются как интерфейсы. Для таких классов можно убрать это требование, но добавить какое-то требование по неймингу, например I
перед именем: IDisposable
.
In this issue I want to discuss about fields order in a class declaration.
Because most code users or readers are first interested in the public interface, not in the implementation details, make sense use the following order: public
, protected
, private
. But there are some drawbacks:
Private field declarations are placed at the end of a class, but constructor (where this fields are initialized) is placed at the beginning of a class. For big classes you need often scroll code up and down each time when you want to see variable type before initialization. In other words, distance between declaration and initialization of some field can be long, but we prefer keep it short:
Each variable should be declared as close as possible to the place where it's first used.
TypeScript allow short field declaration:
class Foo {
constructor(private _bar: number) {}
}
instead
class Foo {
constructor(bar: number) {
this._bar = bar;
}
// some code...
private _bar: number;
}
Or allow initialize variable with declaration:
class Foo {
constructor() {
// initialize other fields
}
// some code...
private _map: Map<string, string> = new Map();
}
In this cases fields initialization is happen in different places.
Should static
fields be placed before or after non-static fields?
I propose adding these two rules:
"disallowSpaceBeforeComma": true,
"requireSpaceAfterComma": true
There are two contradicting rules:
function foo() {
// ...
}
var bar = function () {
// ...
};
In my opinion, there should be always a space before parentheses in function declaration.
We prefer using single var
block at the beginning of function or block. Like that:
var x = 'a',
y = {
z: 'x'
};
Our arguments are:
(a) first of all, our code style says, that all function arguments casting and default values assigning must be done at the beginning of the function, like that:
function addEvent (options) {
var type = Array.isArray(options.type) ? options.type: [ options.type ],
context = options.context || null;
}
That, obviously, greatly increases readability and decreases risks of making casting errors.
(b) in second, every variable must be initialized.
This explicitly leads to an idea of having variables initialization
block. There is no such construction in JavaScript, so we use single var
to denote such block (note that we add additional indent to any objects/functions declared inside var
block.
As for requirement to declare variables at the point when they're used first time, this is, in our opinion, bad architectural principle. Partly because of (a) rule, since you can't easily check whether every variable is initialized without reading entire function through, but mostly because such code is obviously under-normalized:
var x = 'a';
// code
// block
// no. 1
var y = 'b';
// code
// block
// no. 2
Obviously, such function must be split into two different functions comprising block no. 1 and block no. 2 respectively.
So, our suggestion is:
example:
var UpperCamelCase = {
UPPER_CASE: 0,
DELETED: 1,
REED: 2
};
Let's discuss.
upd: add semi-colon.
Boolean constructor is not meant to be used as a cast operator.
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Boolean
The most obvious example is Boolean(new Boolean(false))
expression, which is truthy.
Since casting to Boolean is usually done to be used in conditions, I'd prefer to use casting expression which behaves exactly the same way as condition checking in JavaScript, i.e. !!variable
, though it's a bit non-obvious.
Should we specify function as async
if it doesn't have await
expression? E.g.:
async function test(): Promise<void> {
return foo();
}
Or should use async
only with await
:
async function test1(): Promise<void> {
await foo();
return bar();
}
// Note: no async here
function test2(): Promise<void> {
return bar();
}
It has already released, but not supported by this preset
Styleguide says: Parentheses [...] Should be used only if it is required of the expression's syntax or semantics.
In my opinion, parentheses should be always use to indicate logical meaning of expression. Redundant parentheses are good.
I suggest to add a rule that requires use of identifiers in object literals for ES6 and TS code:
// Bad:
{foo: foo}
{
foo: computeFoo(),
bar: bar,
baz: 1
}
// Good:
{foo}
{
foo: computeFoo(),
bar,
baz: 1
}
I hava this error with loris codestyle:
Missing space before opening round brace at ./examples/config.js :
4 |
5 |class Config {
6 | constructor() {
-----------------------^
7 | this._pagePath = path.join(__dirname, 'base-page.html');
8 | }
Missing space before opening round brace at ./examples/config.js :
8 | }
9 |
10 | before() {
------------------^
11 | return new Promise((resolve, reject) => {
12 | fs.readFile(this._pagePath, (err, data) => {
2 code style errors found.
In my opinion, we should recommend using Array.prototype.reduce
alongside map
and Object.keys
. Code like
var obj = arr.reduce(function (obj, val) {
obj[val.key] = obj[val.value];
return obj;
}, {});
is much nicer than
var obj = {};
arr.forEach(function (val) {
obj[val.key] = obj[val.value];
});
I suggest we add to the code style a requirement for functions and methods to always have return type specified explicitly. There're two points behind this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.