Key Sections:
- Variable
- Class
- Component
- Interface
- Type
- Namespace
- Enum
null
vs.undefined
- Formatting
- Single vs. Double Quotes
- Use semicolons
- Annotate Arrays as
Type[]
- File Names
type
vsinterface
- One-line
if
statements - imports
- KeyboardEvents
- Use
camelCase
for variable and function names
Reason: Conventional JavaScript
Bad
var FooVar;
function BarFunc() {}
Good
var fooVar;
function barFunc() {}
- Use
PascalCase
for class names.
Reason: This is actually fairly conventional in standard JavaScript.
Bad
class foo {}
Good
class Foo {}
- Use
camelCase
of class members and methods
Reason: Naturally follows from variable and function naming convention.
Bad
class Foo {
Bar: number;
Baz() {}
}
Good
class Foo {
bar: number;
baz() {}
}
- Use
PascalCase
for component name, even if function component.
Reason: Follows React naming convention.
Bad
const component: React.FC = () => {
return <subComponent />;
};
Good
const Component: React.FC = () => {
return <SubComponent />;
};
- Use
PascalCase
for name.
Reason: Similar to class
- Use
camelCase
for members.
Reason: Similar to class
- Don't prefix with
I
Reason: Unconventional.
lib.d.ts
defines important interfaces without anI
(e.g. Window, Document etc).
Bad
interface IFoo {}
Good
interface Foo {}
- Use
PascalCase
for name.
Reason: Similar to class
- Use
camelCase
for members.
Reason: Similar to class
- Use
ALL_CAPS
for action types.
Reason: Follows Redux naming convention
- Use
PascalCase
for names
Reason: Convention followed by the TypeScript team. Namespaces are effectively just a class with static members. Class names are
PascalCase
=> Namespace names arePascalCase
Bad
namespace foo {}
Good
namespace Foo {}
- Use
PascalCase
for enum names
Reason: Similar to Class. Is a Type.
Bad
enum color {}
Good
enum Color {}
- Use
PascalCase
for enum member
Reason: Convention followed by TypeScript team i.e. the language creators e.g
SyntaxKind.StringLiteral
. Also helps with translation (code generation) of other languages into TypeScript.
Bad
enum Color {
red,
}
Good
enum Color {
Red,
}
- Prefer not to use either for explicit unavailability
Reason: these values are commonly used to keep a consistent structure between values. In TypeScript you use types to denote the structure
Bad
let foo = { x: 123, y: undefined };
Good
let foo: { x: number; y?: number } = { x: 123 };
- Use
undefined
in general (do consider returning an object like{valid:boolean,value?:Foo}
instead)
Bad
return null;
Good
return undefined;
- Use
null
where its a part of the API or conventional
Reason: It is conventional in Node.js e.g.
error
isnull
for NodeBack style callbacks.
Bad
cb(undefined);
Good
cb(null);
- Use truthy check for objects being
null
orundefined
Bad
if (error === null)
Good
if (error)
Remark: Use
===
/!==
to check fornull
/undefined
on primitives that might be other falsy values (like''
,0
,false
).
Use Prettier to format TypeScript code as described in the README.
Reason: Reduce the cognitive overload on the team.
- Prefer double quotes (").
Reason: Follows Prettier naming convention.
- Use semicolons.
Reasons: Explicit semicolons helps language formatting tools give consistent results. Missing ASI (automatic semicolon insertion) can trip new devs e.g.
foo() \n (function(){})
will be a single statement (not two). TC39 warning on this as well. Example teams: airbnb, idiomatic, google/angular, facebook/react, Microsoft/TypeScript.
- Annotate arrays as
foos:Foo[]
instead offoos:Array<Foo>
.
Reasons: Its easier to read. Its used by the TypeScript team. Makes easier to know something is an array as the mind is trained to detect
[]
.
Name files with camelCase
. E.g. accordion.tsx
, myControl.tsx
, utils.ts
, map.ts
etc.
Reason: Conventional across many JS teams.
- Use
type
when you might need a union or intersection:
type Foo = number | { someProperty: number }
- Use
interface
when you wantextends
orimplements
e.g
interface Foo {
foo: string;
}
interface FooBar extends Foo {
bar: string;
}
class X implements FooBar {
foo: string;
bar: string;
}
- Otherwise use whatever makes you happy that day.
Add braces to one-line if
statements;
Good
if (isEmpty) {
callFun();
}
Bad
if (isEmpty)
callFun();
Reason: Avoiding braces can cause developers to miss bugs, such as Apple's infamous goto-fail bug
Use absolute import
statements everywhere for consistency.
Good
import { getAllProjects } from "backend";
import { Project } from "types/project";
Bad
import { getAllProjects } from "../../../../backend";
import { Project } from "../../../../types/project";
Reason: Provides consistency for imports across all files and shortens imports of commonly used top level modules. Developers don't have to count
../
to know where a module is, they can simply start from the root ofsrc/
.
Use ts-key-enum
when comparing to React.KeyboardEvent
s.
Good
import { Key } from "ts-key-enum";
if (event.key === Key.Enter) {
}
Bad
if (event.key === "Enter") {
}
Reason: Avoid typos and increase the number of mistakes that can be caught at compile time.