TypeScript Style Guide and Coding Conventions
Key Sections:
Variable and Function
- Use
camelCase
for variable and function names
Reason: Conventional JavaScript
Bad
var FooVar;
function BarFunc() { }
Good
var fooVar;
function barFunc() { }
Class
- 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() { }
}
Interface
- 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 {
}
Type
- Use
PascalCase
for name.
Reason: Similar to class
- Use
camelCase
for members.
Reason: Similar to class
Namespace
- 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 {
}
Enum
- 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
}
Null vs. Undefined
- 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 it's 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)
- Use
== null
/!= null
(not===
/!==
) to check fornull
/undefined
on primitives as it works for bothnull
/undefined
but not other falsy values (like''
,0
,false
) e.g.
Bad
if (error !== null) // does not rule out undefined
Good
if (error != null) // rules out both null and undefined
Formatting
The TypeScript compiler ships with a very nice formatting language service. Whatever output it gives by default is good enough to reduce the cognitive overload on the team.
Use tsfmt
to automatically format your code on the command line. Also, your IDE (atom/vscode/vs/sublime) already has formatting support built-in.
Examples:
// Space before type i.e. foo:<space>string
const foo: string = "hello";
Quotes
- Prefer single quotes (
'
) unless escaping.
Reason: More JavaScript teams do this (e.g. airbnb, standard, npm, node, google/angular, facebook/react). It's easier to type (no shift needed on most keyboards). Prettier team recommends single quotes as well
Double quotes are not without merit: Allows easier copy paste of objects into JSON. Allows people to use other languages to work without changing their quote character. Allows you to use apostrophes e.g.
He's not going.
. But I'd rather not deviate from where the JS Community is fairly decided.
- When you can't use double quotes, try using back ticks (`).
Reason: These generally represent the intent of complex enough strings.
Spaces
- Use
2
spaces. Not tabs.
Reason: More JavaScript teams do this (e.g. airbnb, idiomatic, standard, npm, node, google/angular, facebook/react). The TypeScript/VSCode teams use 4 spaces but are definitely the exception in the ecosystem.
Semicolons
- 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.
Array
- Annotate arrays as
foos: Foo[]
instead offoos: Array<Foo>
.
Reasons: It's easier to read. It's used by the TypeScript team. Makes easier to know something is an array as the mind is trained to detect
[]
.
Filename
Name files with camelCase
. E.g. utils.ts
, map.ts
etc.
Reason: Conventional across many JS teams.
When the file exports a component and your framework (like React) wants component to be PascalCased, use pascal case file name to match e.g. Accordion.tsx
, MyControl.tsx
.
Reason: Helps with consistency (little overthought required) and its what the ecosystem is doing.
type vs. interface
- 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. I use type
==
or ===
Both are mostly safe for TypeScript users. I use ===
as that is what is used in the TypeScript codebase.