
Google Styleguides Skills
- 32 installs
- 8 repo stars
- Updated February 25, 2026
- testdino-hq/google-styleguides-skills
Helps with ai & agent building tasks during AI-assisted development.
About
google-styleguides-skills is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- google-styleguides-skills
- AI & Agent Building
- AI-coding skill
Google Styleguides Skills by the numbers
- 32 all-time installs (skills.sh)
- +3 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #9,101 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/testdino-hq/google-styleguides-skills --skill google-styleguides-skillsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 32 |
|---|---|
| repo stars | ★ 8 |
| Last updated | February 25, 2026 |
| Repository | testdino-hq/google-styleguides-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Google AngularJS Style Guide
Official Google AngularJS coding standards for consistent Angular 1.x applications.
Note: This guide covers AngularJS (Angular 1.x). For modern Angular (2+), see the Angular style guide.
Golden Rules
1. One component per file — easier to maintain and test 2. Use controllerAs syntax — avoid $scope when possible 3. Services for business logic — keep controllers thin 4. Explicit dependency injection — array annotation or $inject 5. Modular structure — organize by feature, not type 6. Use directives — for DOM manipulation only 7. Avoid `$rootScope` — use services for shared state
Quick Reference
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Modules | lowerCamelCase | myApp, myApp.users |
| Controllers | UpperCamelCase + Ctrl | UserCtrl, HomeCtrl |
| Services/Factories | UpperCamelCase | UserService, AuthFactory |
| Directives | lowerCamelCase | myDirective, userCard |
| Filters | lowerCamelCase | dateFormat, currencyDisplay |
| Files | feature.type.js | user.controller.js |
Controllers
// ✓ CORRECT - controllerAs syntax
angular.module('myApp')
.controller('UserCtrl', UserCtrl);
UserCtrl.$inject = ['UserService', '$log'];
function UserCtrl(UserService, $log) {
var vm = this; // vm = viewModel
vm.users = [];
vm.loadUsers = loadUsers;
activate();
function activate() {
loadUsers();
}
function loadUsers() {
return UserService.getAll()
.then(function(users) {
vm.users = users;
return vm.users;
});
}
}Services
// ✓ CORRECT - service for business logic
angular.module('myApp')
.factory('UserService', UserService);
UserService.$inject = ['$http', '$log'];
function UserService($http, $log) {
var service = {
getAll: getAll,
getById: getById,
create: create
};
return service;
function getAll() {
return $http.get('/api/users')
.then(function(response) {
return response.data;
});
}
function getById(id) {
return $http.get('/api/users/' + id)
.then(function(response) {
return response.data;
});
}
function create(user) {
return $http.post('/api/users', user);
}
}Directives
// ✓ CORRECT - directive for DOM manipulation
angular.module('myApp')
.directive('userCard', userCard);
function userCard() {
return {
restrict: 'E',
scope: {
user: '=',
onSelect: '&'
},
templateUrl: 'user-card.html',
controller: 'UserCardCtrl',
controllerAs: 'vm',
bindToController: true
};
}Dependency Injection
// ✓ CORRECT - explicit $inject annotation (minification-safe)
MyCtrl.$inject = ['$scope', '$http', 'UserService'];
function MyCtrl($scope, $http, UserService) {
// ...
}
// ✗ INCORRECT - inline array (verbose) or no annotation (breaks minification)
angular.module('myApp').controller('MyCtrl', ['$scope', function($scope) {}]);Modules
// ✓ CORRECT - one module definition per file
// app.module.js
angular.module('myApp', ['ngRoute', 'myApp.users', 'myApp.auth']);
// users/users.module.js
angular.module('myApp.users', []);
// ✗ INCORRECT - defining everything in one file
angular.module('myApp', []).controller(...).service(...).directive(...);Templates
<!-- ✓ CORRECT - controllerAs in template -->
<div ng-controller="UserCtrl as vm">
<h1>{{ vm.title }}</h1>
<ul>
<li ng-repeat="user in vm.users track by user.id">
{{ user.name }}
</li>
</ul>
<button ng-click="vm.loadUsers()">Reload</button>
</div>Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Business logic in controllers | Move to services/factories |
Using $scope directly | Use controllerAs with vm alias |
| Implicit DI (breaks minification) | Use $inject or array annotation |
| DOM manipulation in controllers | Use directives |
| Everything in one module | Organize by feature into sub-modules |
Using $rootScope for shared state | Use a service instead |
| Watchers for every change | Use one-time binding :: where possible |
When to Use This Guide
- Maintaining AngularJS 1.x applications
- Code reviews for legacy Angular projects
- Onboarding new team members to AngularJS projects
Install
npx skills add testdino-hq/google-styleguides-skills/angularjsFull Guide
See angularjs.md for complete details, examples, and edge cases.
Google AngularJS Style Guide
Source: https://google.github.io/styleguide/angularjs-google-style.html
Golden Rules
1. Use Closure's `goog.require` and `goog.provide` — for dependency management 2. Controllers are classes — define on prototype 3. Use 'controller as' syntax — export controller to scope 4. Directives for DOM manipulation — keep controllers DOM-free 5. Use `module.service` for services — not factory or provider 6. Reserve `$` for Angular/jQuery — don't prefix your own identifiers
---
1. Module Definition
// CORRECT - define module with goog.provide
goog.provide('myapp.users.UserController');
goog.provide('myapp.users.userService');
// CORRECT - module definition
myapp.users.module = angular.module('myapp.users', [
'ngRoute',
'ngResource'
]);---
2. Controllers
// CORRECT - controller as class
/**
* User controller.
* @param {!myapp.users.UserService} userService
* @constructor
* @ngInject
* @export
*/
myapp.users.UserController = function(userService) {
/** @private {!myapp.users.UserService} */
this.userService_ = userService;
/** @export {string} */
this.userName = '';
};
/**
* Loads user data.
* @param {number} userId
* @export
*/
myapp.users.UserController.prototype.loadUser = function(userId) {
this.userService_.getUser(userId).then(function(user) {
this.userName = user.name;
}.bind(this));
};
// Register controller
myapp.users.module.controller(
'UserController',
myapp.users.UserController);---
3. Controller As Syntax
<!-- CORRECT - use 'controller as' -->
<div ng-controller="myapp.users.UserController as userCtrl">
<h1>{{userCtrl.userName}}</h1>
<button ng-click="userCtrl.loadUser(123)">Load User</button>
</div>---
4. Services
// CORRECT - service as class
/**
* User service.
* @param {!angular.$http} $http
* @constructor
* @ngInject
*/
myapp.users.UserService = function($http) {
/** @private {!angular.$http} */
this.http_ = $http;
};
/**
* Gets user by ID.
* @param {number} userId
* @return {!angular.$q.Promise}
*/
myapp.users.UserService.prototype.getUser = function(userId) {
return this.http_.get('/api/users/' + userId);
};
// Register service
myapp.users.module.service('userService', myapp.users.UserService);---
5. Directives
// CORRECT - directive as function returning DDO
goog.provide('myapp.directives.userCard');
/**
* User card directive.
* @return {angular.Directive}
*/
myapp.directives.userCard = function() {
return {
restrict: 'E',
scope: {
user: '='
},
templateUrl: 'templates/user-card.html',
controller: 'UserCardController',
controllerAs: 'ctrl',
bindToController: true
};
};
// Register directive
myapp.module.directive('userCard', myapp.directives.userCard);---
6. Dependency Injection
// CORRECT - use @ngInject annotation
/**
* @param {!angular.$http} $http
* @param {!myapp.UserService} userService
* @constructor
* @ngInject
*/
myapp.MyController = function($http, userService) {
this.http_ = $http;
this.userService_ = userService;
};---
7. Naming Conventions
// CORRECT - naming
myapp.users.UserController // Controller class
myapp.users.UserService // Service class
myapp.directives.userCard // Directive function
// AVOID - don't use $ prefix
myapp.users.$UserService // AVOID
this.$myProperty = value; // AVOID---
8. Scopes
// CORRECT - use controller properties, not $scope
myapp.MyController = function() {
/** @export {string} */
this.message = 'Hello';
};
// AVOID - building up $scope object
myapp.MyController = function($scope) {
$scope.message = 'Hello'; // AVOID
};---
9. Promises
// CORRECT - use promises
myapp.UserService.prototype.getUser = function(userId) {
return this.http_.get('/api/users/' + userId)
.then(function(response) {
return response.data;
})
.catch(function(error) {
console.error('Failed to get user:', error);
throw error;
});
};---
10. Testing
// CORRECT - Jasmine test
describe('UserController', function() {
var ctrl;
var mockUserService;
beforeEach(module('myapp.users'));
beforeEach(inject(function($controller) {
mockUserService = {
getUser: jasmine.createSpy('getUser')
};
ctrl = $controller('UserController', {
userService: mockUserService
});
}));
it('should load user', function() {
ctrl.loadUser(123);
expect(mockUserService.getUser).toHaveBeenCalledWith(123);
});
});---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
Using $scope directly | Use 'controller as' syntax |
Using $ prefix | Reserve for Angular/jQuery |
| DOM in controllers | Use directives for DOM manipulation |
Using factory | Use service for classes |
Missing @ngInject | Add annotation for DI |
| Not using Closure | Use goog.provide/goog.require |
Google Common Lisp Style Guide
Source: https://google.github.io/styleguide/lispguide.xml
Golden Rules
1. Use lowercase with hyphens — for symbols 2. 2-space indentation — for readability 3. Descriptive names — clarity over brevity 4. Document all exported symbols — with docstrings 5. Use packages — for namespace management 6. Prefer functional style — minimize side effects
---
1. Naming
| Element | Convention | Example |
|---|---|---|
| Functions | lowercase-with-hyphens | calculate-total |
| Variables | lowercase-with-hyphens | user-count |
| Constants | +constant-name+ | +max-retries+ |
| Global vars | global-var | *database-connection* |
| Predicates | ends-with-p | active-p, empty-p |
| Type predicates | ends-with-p | stringp, numberp |
;; CORRECT - naming conventions
(defun calculate-average (numbers)
"Calculate the average of a list of numbers."
(/ (reduce #'+ numbers) (length numbers)))
(defparameter *database-url* "localhost:5432")
(defconstant +max-connections+ 100)
(defun active-p (user)
"Return T if user is active."
(eq (user-status user) :active))---
2. Functions
;; CORRECT - function definition with docstring
(defun process-user (user)
"Process a user record and return the result.
USER must be a valid user object."
(when (active-p user)
(update-last-seen user)
(send-notification user)))
;; CORRECT - function with multiple values
(defun divide-with-remainder (dividend divisor)
"Return quotient and remainder."
(values (floor dividend divisor)
(mod dividend divisor)))
;; CORRECT - lambda functions
(mapcar (lambda (x) (* x 2)) '(1 2 3 4 5))---
3. Variables
;; CORRECT - let for local bindings
(let ((x 10)
(y 20))
(+ x y))
;; CORRECT - let* for sequential bindings
(let* ((x 10)
(y (* x 2)))
y)
;; CORRECT - defparameter for dynamic variables
(defparameter *default-timeout* 30
"Default timeout in seconds.")
;; CORRECT - defvar for variables that shouldn't be reset
(defvar *connection-pool* nil
"Global connection pool.")---
4. Control Flow
;; CORRECT - if for simple conditionals
(if (> x 10)
(print "Greater")
(print "Not greater"))
;; CORRECT - when for single branch
(when (active-p user)
(process-user user)
(log-activity user))
;; CORRECT - unless for negated condition
(unless (empty-p queue)
(process-next-item queue))
;; CORRECT - cond for multiple conditions
(cond
((< x 0) "negative")
((= x 0) "zero")
((> x 0) "positive")
(t "unknown"))
;; CORRECT - case for dispatch
(case status
(:active "Active")
(:inactive "Inactive")
(:pending "Pending")
(otherwise "Unknown"))---
5. Loops
;; CORRECT - dolist for iterating lists
(dolist (item items)
(process-item item))
;; CORRECT - dotimes for counting
(dotimes (i 10)
(print i))
;; CORRECT - loop macro
(loop for i from 1 to 10
collect (* i i))
(loop for item in items
when (active-p item)
collect item)---
6. Data Structures
;; CORRECT - lists
(defvar *users* '("Alice" "Bob" "Charlie"))
;; CORRECT - property lists
(defvar *config* '(:host "localhost"
:port 5432
:database "mydb"))
;; CORRECT - hash tables
(defvar *user-cache* (make-hash-table :test 'equal))
(setf (gethash "user-123" *user-cache*) user-object)
;; CORRECT - structures
(defstruct user
id
name
email
(active t))
(defvar *user* (make-user :id 1 :name "Alice"))---
7. Macros
;; CORRECT - simple macro
(defmacro with-timing (&body body)
"Execute BODY and print execution time."
`(let ((start (get-internal-real-time)))
(prog1
(progn ,@body)
(format t "Time: ~A~%"
(- (get-internal-real-time) start)))))
;; Usage
(with-timing
(expensive-operation))---
8. Error Handling
;; CORRECT - condition handling
(handler-case
(risky-operation)
(file-error (e)
(format t "File error: ~A~%" e))
(error (e)
(format t "General error: ~A~%" e)))
;; CORRECT - unwind-protect for cleanup
(unwind-protect
(progn
(open-resource)
(use-resource))
(close-resource))---
9. Packages
;; CORRECT - package definition
(defpackage :myapp.users
(:use :cl)
(:export :user
:make-user
:user-name
:user-email
:process-user))
(in-package :myapp.users)
;; CORRECT - using symbols from other packages
(myapp.database:connect *database-url*)---
10. Documentation
;; CORRECT - comprehensive docstrings
(defun fetch-user (user-id)
"Fetch user by USER-ID from the database.
USER-ID must be a positive integer.
Returns a USER object or NIL if not found.
Signals DATABASE-ERROR if connection fails."
(when (not (plusp user-id))
(error "USER-ID must be positive"))
(database-query "SELECT * FROM users WHERE id = ?" user-id))---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| CamelCase names | Use lowercase-with-hyphens |
| Missing docstrings | Document all exported symbols |
| Not using packages | Define packages for namespacing |
| Ignoring errors | Use proper error handling |
| Side effects everywhere | Prefer functional style |
| Inconsistent indentation | Use 2-space indentation |
Google C++ Style Guide
Source: https://google.github.io/styleguide/cppguide.html
Golden Rules
1. Target C++20 — avoid non-standard extensions 2. 80-character line limit — for readability 3. 2-space indentation — no tabs 4. Use `const` liberally — for correctness and thread safety 5. Avoid exceptions — Google code doesn't use C++ exceptions 6. Smart pointers for ownership — std::unique_ptr and std::shared_ptr 7. Header guards — use PROJECT_PATH_FILE_H_ format
---
1. Headers
// CORRECT - self-contained header with guard
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
#include <string>
#include "base/basictypes.h"
class Baz {
public:
void DoSomething();
};
#endif // FOO_BAR_BAZ_H_Include Order
1. Related header 2. C system headers 3. C++ standard library headers 4. Other libraries' headers 5. Your project's headers
---
2. Naming
| Element | Convention | Example |
|---|---|---|
| Files | snake_case | url_table.cc |
| Types | UpperCamelCase | UrlTable |
| Variables | snake_case | table_name |
| Functions | UpperCamelCase | AddTableEntry() |
| Constants | kConstantName | kDaysInAWeek |
| Macros | UPPER_SNAKE_CASE | MY_MACRO |
| Class members | snake_case_ | table_name_ (trailing underscore) |
---
3. Classes
// CORRECT
class MyClass {
public:
MyClass(); // Constructor
~MyClass(); // Destructor
void DoSomething();
int GetValue() const { return value_; }
private:
int value_;
std::string name_;
};Key Rules
- Declare data members
private(except in structs) - Use trailing underscore for private data members
- Mark single-argument constructors
explicit - Use
= deletefor uncopyable classes - Prefer composition over inheritance
---
4. Functions
// CORRECT - return type on same line
ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
DoSomething();
return result;
}
// CORRECT - wrap long parameter lists
ReturnType LongClassName::ReallyLongFunctionName(
Type par_name1, // 4 space indent
Type par_name2,
Type par_name3) {
DoSomething();
}---
5. Smart Pointers
// CORRECT - use unique_ptr for exclusive ownership
std::unique_ptr<Foo> FooFactory();
void FooConsumer(std::unique_ptr<Foo> ptr);
// CORRECT - use shared_ptr sparingly
std::shared_ptr<const Foo> immutable_foo;
// AVOID - never use auto_ptr
std::auto_ptr<Foo> foo; // AVOID---
6. Modern C++ Features
// CORRECT - use auto for complex types
auto it = my_map.find(key);
auto widget = std::make_unique<Widget>(arg1, arg2);
// CORRECT - use range-based for loops
for (const auto& item : container) {
Process(item);
}
// CORRECT - use nullptr, not NULL
Foo* ptr = nullptr;
// CORRECT - use constexpr for compile-time constants
constexpr int kArraySize = 100;---
7. Avoid These Features
| Feature | Why Avoid |
|---|---|
| Exceptions | Not used at Google; use error codes |
RTTI (dynamic_cast) | Use sparingly; prefer virtual methods |
| Multiple inheritance | Complex; use sparingly |
| Operator overloading | Use judiciously; must be obvious |
| Default arguments | Can be confusing; prefer overloads |
---
8. Formatting
// CORRECT - braces and spacing
if (condition) {
DoSomething();
} else {
DoSomethingElse();
}
// CORRECT - pointer/reference alignment
char* c;
const std::string& str;
// CORRECT - function calls
DoSomething(argument1, argument2, argument3);
// CORRECT - wrap long calls
DoSomething(
argument1, argument2, // 4 space indent
argument3, argument4);---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Using exceptions | Use error codes or absl::Status |
Bare new/delete | Use smart pointers |
NULL | Use nullptr |
| C-style casts | Use C++ casts (static_cast, etc.) |
using namespace std | Never in headers; avoid in .cc files |
| Mutable globals | Use singletons or dependency injection |
Google C# Style Guide
Source: https://google.github.io/styleguide/csharp.html
Golden Rules
1. Follow Microsoft C# Coding Conventions — as baseline 2. PascalCase for public members — methods, properties, classes 3. camelCase for private fields — with underscore prefix _fieldName 4. Use `var` judiciously — when type is obvious 5. Prefer expression-bodied members — for simple methods 6. Use nullable reference types — enable in C# 8.0+
---
1. Naming
| Element | Convention | Example |
|---|---|---|
| Classes/Interfaces | PascalCase | UserService, IRepository |
| Methods | PascalCase | GetUserById() |
| Properties | PascalCase | FirstName |
| Public fields | PascalCase | MaxValue |
| Private fields | _camelCase | _userName |
| Local variables | camelCase | userCount |
| Parameters | camelCase | userId |
| Constants | PascalCase | MaxRetries |
---
2. Classes and Interfaces
// CORRECT
public class UserService
{
private readonly IUserRepository _repository;
private int _userCount;
public UserService(IUserRepository repository)
{
_repository = repository;
}
public User GetUserById(int userId)
{
return _repository.FindById(userId);
}
}
// CORRECT - interface naming
public interface IUserRepository
{
User FindById(int id);
void Save(User user);
}---
3. Properties
// CORRECT - auto-properties
public string FirstName { get; set; }
public int Age { get; private set; }
public bool IsActive { get; }
// CORRECT - expression-bodied property
public string FullName => $"{FirstName} {LastName}";
// CORRECT - property with backing field
private string _email;
public string Email
{
get => _email;
set => _email = value?.Trim();
}---
4. Methods
// CORRECT - expression-bodied method
public int Add(int a, int b) => a + b;
// CORRECT - regular method
public void ProcessUser(User user)
{
if (user == null)
throw new ArgumentNullException(nameof(user));
_repository.Save(user);
}
// CORRECT - async method
public async Task<User> GetUserAsync(int userId)
{
return await _repository.FindByIdAsync(userId);
}---
5. Control Flow
// CORRECT - braces on new line
if (condition)
{
DoSomething();
}
else
{
DoSomethingElse();
}
// CORRECT - switch expression (C# 8.0+)
var result = status switch
{
Status.Active => "Active",
Status.Inactive => "Inactive",
_ => "Unknown"
};
// CORRECT - pattern matching
if (obj is User user)
{
Console.WriteLine(user.Name);
}---
6. LINQ
// CORRECT - query syntax
var activeUsers = from user in users
where user.IsActive
orderby user.Name
select user;
// CORRECT - method syntax
var activeUsers = users
.Where(u => u.IsActive)
.OrderBy(u => u.Name)
.ToList();---
7. Null Handling
// CORRECT - null-conditional operator
var length = user?.Name?.Length ?? 0;
// CORRECT - null-coalescing operator
var name = user.Name ?? "Unknown";
// CORRECT - nullable reference types (C# 8.0+)
public class User
{
public string Name { get; set; } = string.Empty; // Non-nullable
public string? MiddleName { get; set; } // Nullable
}---
8. Exception Handling
// CORRECT
try
{
ProcessData();
}
catch (ArgumentException ex)
{
_logger.LogError(ex, "Invalid argument");
throw;
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error");
throw new ApplicationException("Processing failed", ex);
}
finally
{
Cleanup();
}---
9. Using Statements
// CORRECT - using declaration (C# 8.0+)
using var stream = File.OpenRead("file.txt");
// stream is disposed at end of scope
// CORRECT - traditional using
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// Use connection
}---
10. Modern C# Features
// CORRECT - record types (C# 9.0+)
public record User(int Id, string Name);
// CORRECT - init-only properties (C# 9.0+)
public class User
{
public int Id { get; init; }
public string Name { get; init; }
}
// CORRECT - target-typed new (C# 9.0+)
User user = new(1, "Alice");
List<string> names = new();---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Public fields | Use properties instead |
| Hungarian notation | Use meaningful names without type prefixes |
Catching Exception | Catch specific exceptions |
Not using async/await | Use for I/O-bound operations |
| Ignoring nullable warnings | Enable and fix nullable reference types |
| Not disposing resources | Use using statements |
Google Go Style Guide
Source: https://google.github.io/styleguide/go/
Golden Rules
1. Run `gofmt` — all code must be formatted with gofmt 2. Handle errors explicitly — never ignore returned errors with _ 3. Comment exported identifiers — all exported names must have doc comment 4. Return early — prefer guard clauses over deep nesting 5. Keep interfaces small — one or two methods is ideal 6. Name things clearly — short names for short scopes
---
1. Naming
// packages: lowercase, no underscores
package userservice
// exported: UpperCamelCase
type UserService struct { }
func GetUser(id int) (*User, error) { return nil, nil }
// unexported: lowerCamelCase
type userRepository struct { }
func getUserByID(id int) (*User, error) { return nil, nil }
// constants: UpperCamelCase (not UPPER_SNAKE_CASE)
const MaxRetries = 3
const defaultTimeout = 30
// acronyms: all uppercase
type HTTPClient struct { }
func parseURL(raw string) string { return raw }---
2. Error Handling
// CORRECT - always handle errors
file, err := os.Open("data.txt")
if err != nil {
return fmt.Errorf("opening data file: %w", err)
}
defer file.Close()
// CORRECT - wrap errors with context
func processUser(id int) error {
user, err := getUser(id)
if err != nil {
return fmt.Errorf("processUser(%d): %w", id, err)
}
return nil
}
// INCORRECT - ignoring errors
file, _ := os.Open("data.txt") // never ignore errors---
3. Interfaces
// CORRECT - small, focused interfaces
type Reader interface {
Read(p []byte) (n int, err error)
}
// CORRECT - interface composition
type ReadWriter interface {
Reader
Writer
}
// AVOID - large interfaces (too many methods)---
4. Structs
// CORRECT
type User struct {
ID int
Name string
Email string
}
// CORRECT - struct literal with field names
user := User{
ID: 1,
Name: "Alice",
Email: "alice@example.com",
}
// INCORRECT - positional struct literal
user := User{1, "Alice", "alice@example.com"} // fragile---
5. Goroutines
// CORRECT - always synchronize
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item Item) {
defer wg.Done()
process(item)
}(item)
}
wg.Wait()---
6. Testing (Table-Driven)
// CORRECT - table-driven tests
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 1, 2, 3},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := add(tt.a, tt.b)
if got != tt.expected {
t.Errorf("add(%d, %d) = %d; want %d", tt.a, tt.b, got, tt.expected)
}
})
}
}---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Ignoring errors with _ | Always handle returned errors |
| Large interfaces | Keep to 1-2 methods |
| Positional struct literals | Use field names |
| No doc comments on exports | Add doc comment to every export |
| UPPER_SNAKE_CASE constants | Use UpperCamelCase |
| Leaking goroutines | Always ensure goroutines terminate |
Google HTML/CSS Style Guide
Source: https://google.github.io/styleguide/htmlcssguide.html
Golden Rules
1. Use HTTPS — for all embedded resources 2. 2-space indentation — no tabs 3. Lowercase everything — elements, attributes, selectors 4. Valid HTML/CSS — use validators 5. Semantic HTML — use elements for their intended purpose 6. Separate concerns — structure (HTML) from presentation (CSS)
---
HTML
1. Document Type
<!-- CORRECT - always use HTML5 doctype -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Page Title</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>---
2. Semantic HTML
<!-- CORRECT - use semantic elements -->
<header>
<nav>
<a href="/">Home</a>
</nav>
</header>
<main>
<article>
<h1>Article Title</h1>
<p>Article content...</p>
</article>
</main>
<footer>
<p>© 2024 Company</p>
</footer>
<!-- AVOID - div soup -->
<div class="header">
<div class="nav">
<div class="link">Home</div>
</div>
</div>---
3. Attributes
<!-- CORRECT - use double quotes, lowercase -->
<img src="logo.png" alt="Company Logo">
<a href="/about" class="nav-link">About</a>
<!-- CORRECT - omit type for CSS and JS -->
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<!-- AVOID -->
<img src='logo.png' alt='Company Logo'> <!-- single quotes -->
<link rel="stylesheet" href="style.css" type="text/css"> <!-- unnecessary type -->---
4. Formatting
<!-- CORRECT - new line for block elements -->
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>30</td>
</tr>
</tbody>
</table>---
5. Accessibility
<!-- CORRECT - provide alt text -->
<img src="chart.png" alt="Sales chart showing 20% growth">
<!-- CORRECT - use labels for form inputs -->
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<!-- CORRECT - use semantic headings -->
<h1>Main Title</h1>
<h2>Section Title</h2>
<h3>Subsection Title</h3>---
CSS
1. Naming
/* CORRECT - lowercase with hyphens */
.nav-link { }
.button-primary { }
.user-profile { }
/* AVOID */
.navLink { } /* camelCase */
.nav_link { } /* underscores */
.NAVLINK { } /* uppercase */---
2. Selectors
/* CORRECT - use classes, not IDs */
.example { }
.error { }
/* AVOID - ID selectors */
#example { } /* AVOID */
/* AVOID - type selectors with classes */
ul.example { } /* AVOID */
div.error { } /* AVOID */---
3. Properties
/* CORRECT - use shorthand */
.box {
margin: 0 1em 2em;
padding: 0;
font: 100%/1.6 palatino, georgia, serif;
border-top: 0;
}
/* AVOID - longhand when shorthand available */
.box {
margin-top: 0;
margin-right: 1em;
margin-bottom: 2em;
margin-left: 1em;
}---
4. Units
/* CORRECT - omit units for 0 */
.box {
margin: 0;
padding: 0;
}
/* CORRECT - include leading 0 */
.box {
font-size: 0.8em;
opacity: 0.5;
}
/* CORRECT - use 3-char hex when possible */
.box {
color: #ebc;
background: #fff;
}---
5. Formatting
/* CORRECT - one selector per line */
h1,
h2,
h3 {
font-weight: normal;
line-height: 1.2;
}
/* CORRECT - space after colon */
.box {
color: #333;
background: #fff;
}
/* CORRECT - space before opening brace */
.box {
display: block;
}
/* CORRECT - semicolon after every declaration */
.box {
width: 100%;
height: 50px;
}---
6. Declaration Order (Optional)
/* CORRECT - alphabetical order */
.box {
background: #fff;
border: 1px solid #ddd;
color: #333;
display: block;
font-size: 1em;
margin: 1em;
padding: 1em;
width: 100%;
}---
7. Avoid !important
/* AVOID - !important breaks cascade */
.example {
font-weight: bold !important; /* AVOID */
}
/* CORRECT - use specificity */
.example {
font-weight: bold;
}---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
Using <div> for everything | Use semantic HTML5 elements |
| Missing alt text | Always provide meaningful alt text |
| ID selectors in CSS | Use class selectors |
| Inline styles | Use external stylesheets |
!important overuse | Use proper specificity |
| Missing doctype | Always include <!doctype html> |
| Type attributes | Omit for CSS/JS (HTML5 default) |
Google Java Style Guide
Source: https://google.github.io/styleguide/javaguide.html
Golden Rules
1. 2-space indentation — no tabs 2. Column limit: 100 characters 3. Use `@Override` whenever applicable 4. No wildcard imports — import specific types 5. Braces required even for single-statement blocks 6. One top-level class per file 7. Prefer interfaces for type definitions
---
1. File Structure
// CORRECT
package com.example.project;
import java.util.List;
import java.util.Optional;
public class UserService {
// ...
}---
2. Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Packages | lowercase.dotted | com.example.project |
| Classes/Interfaces | UpperCamelCase | UserService |
| Methods | lowerCamelCase | getUserById |
| Variables | lowerCamelCase | userCount |
| Constants | UPPER_SNAKE_CASE | MAX_RETRIES |
| Type parameters | Single letter | T, RequestT |
---
3. Classes
// CORRECT
public class Animal {
private final String name;
public Animal(String name) {
this.name = name;
}
public String speak() {
return name + " makes a sound.";
}
}---
4. Control Structures
// CORRECT - braces always required
if (condition) {
doSomething();
}
// INCORRECT - no braces
if (condition)
doSomething(); // braces required
// CORRECT - enhanced for loop
for (String item : items) {
process(item);
}---
5. Exception Handling
// CORRECT
try {
processData(input);
} catch (IOException e) {
logger.error("IO error: {}", e.getMessage());
throw new ServiceException("Failed", e);
}
// CORRECT - try-with-resources
try (InputStream in = new FileInputStream(file)) {
return IOUtils.toByteArray(in);
}
// INCORRECT
try {
...
} catch (Exception e) { // too broad
e.printStackTrace(); // don't use printStackTrace
}---
6. Lambdas and Streams
// CORRECT
List<String> names = users.stream()
.filter(u -> u.isActive())
.map(User::getName)
.sorted()
.collect(Collectors.toList());
// CORRECT - method references
users.forEach(System.out::println);---
7. Javadoc
/**
* Finds a user by their unique identifier.
*
* @param userId the user's unique ID
* @return an Optional containing the user, or empty if not found
*/
public Optional<User> findUserById(long userId) { ... }---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Wildcard imports | Specific imports only |
| Omitting braces | Always use braces |
| Missing @Override | Always annotate overridden methods |
| e.printStackTrace() | Use a proper logger |
| Catching Exception broadly | Catch specific exceptions |
| 4-space indentation | Use 2-space indentation |
Google JavaScript Style Guide
Source: https://google.github.io/styleguide/jsguide.html
Golden Rules
1. Use `const` and `let` — never var 2. Use ES6+ features — arrow functions, destructuring, template literals 3. Semicolons are required at end of every statement 4. 2-space indentation — no tabs 5. Single quotes for strings (except JSON) 6. Always use `===` — never == 7. No unused variables
---
1. Variables
// CORRECT
const PI = 3.14159;
let count = 0;
// INCORRECT
var name = 'Alice'; // never use varDestructuring
const [first, second] = array;
const { name, age } = user;
const { name: userName } = user; // with renaming
const { timeout = 5000 } = options; // with defaults---
2. Strings
// CORRECT - single quotes
const name = 'Alice';
// CORRECT - template literals for interpolation
const greeting = `Hello, ${name}!`;
// INCORRECT
const greeting = 'Hello, ' + name + '!'; // use template literals---
3. Functions
// CORRECT - named function declaration
function processData(data) {
return data.filter(Boolean);
}
// CORRECT - arrow functions for callbacks
const doubled = numbers.map(n => n * 2);
// CORRECT - default parameters
function greet(name, greeting = 'Hello') {
return `${greeting}, ${name}!`;
}
// CORRECT - rest parameters
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}---
4. Classes
// CORRECT
class Animal {
#name; // private field
constructor(name) {
this.#name = name;
}
speak() {
return `${this.#name} makes a sound.`;
}
}
// INCORRECT
function Animal(name) { // use class syntax
this.name = name;
}---
5. Modules
// CORRECT - named exports
export function processData(data) { return data; }
export const MAX_SIZE = 100;
// CORRECT - imports
import { processData } from './data-processor.js';---
6. Arrays
// CORRECT - array methods over loops
const evens = numbers.filter(n => n % 2 === 0);
const doubled = numbers.map(n => n * 2);
const total = numbers.reduce((acc, n) => acc + n, 0);
// CORRECT - spread
const combined = [...arr1, ...arr2];
const copy = [...original];---
7. Async/Await
// CORRECT
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
}
// CORRECT - parallel operations
const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);---
8. Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Variables/Functions | lowerCamelCase | getUserById |
| Classes | UpperCamelCase | UserService |
| Constants | UPPER_SNAKE_CASE | MAX_RETRIES |
| Private fields | #name (ES2022) | #privateField |
| Files | lower-kebab-case | user-service.js |
---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
var | Use const/let |
== equality | Use === strict equality |
| String concatenation | Use template literals |
.bind(this) | Use arrow functions |
arguments object | Use rest parameters |
for loops | Use for...of or array methods |
| Missing semicolons | Add semicolons |
Google JSON Style Guide
Source: https://google.github.io/styleguide/jsoncstyleguide.xml
Golden Rules
1. Use camelCase for property names — consistent with JavaScript 2. Use double quotes — for strings 3. No trailing commas — JSON doesn't allow them 4. Use arrays for ordered data — objects for unordered 5. Keep it simple — avoid deep nesting 6. Use consistent date formats — ISO 8601 recommended
---
1. Property Names
// CORRECT - camelCase
{
"firstName": "John",
"lastName": "Doe",
"emailAddress": "john@example.com",
"phoneNumber": "+1-555-0100"
}
// AVOID - snake_case or PascalCase
{
"first_name": "John",
"FirstName": "John"
}---
2. Data Types
// CORRECT - use appropriate types
{
"name": "John Doe",
"age": 30,
"isActive": true,
"balance": 1234.56,
"tags": ["developer", "designer"],
"address": {
"street": "123 Main St",
"city": "New York"
},
"metadata": null
}---
3. Arrays
// CORRECT - arrays for ordered lists
{
"users": [
{
"id": 1,
"name": "Alice"
},
{
"id": 2,
"name": "Bob"
}
]
}
// CORRECT - empty arrays
{
"items": []
}---
4. Objects
// CORRECT - objects for key-value pairs
{
"user": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
},
"settings": {
"theme": "dark",
"language": "en",
"notifications": true
}
}
// CORRECT - empty objects
{
"metadata": {}
}---
5. Dates and Times
// CORRECT - ISO 8601 format
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:45:30.123Z",
"birthDate": "1990-05-20"
}
// AVOID - custom date formats
{
"createdAt": "01/15/2024",
"updatedAt": "15-Jan-2024"
}---
6. Null vs Omission
// CORRECT - use null for explicitly empty values
{
"name": "John",
"middleName": null,
"email": "john@example.com"
}
// ALSO CORRECT - omit optional fields
{
"name": "John",
"email": "john@example.com"
}---
7. Boolean Values
// CORRECT - use true/false
{
"isActive": true,
"isVerified": false,
"hasAccess": true
}
// AVOID - strings or numbers for booleans
{
"isActive": "true",
"isVerified": 0
}---
8. Numbers
// CORRECT - numbers without quotes
{
"count": 42,
"price": 19.99,
"percentage": 0.15,
"scientific": 1.23e-4
}
// AVOID - numbers as strings
{
"count": "42",
"price": "19.99"
}---
9. Formatting
// CORRECT - pretty-printed for readability
{
"user": {
"id": 123,
"name": "John Doe",
"roles": [
"admin",
"editor"
]
}
}
// CORRECT - minified for production
{"user":{"id":123,"name":"John Doe","roles":["admin","editor"]}}---
10. API Responses
// CORRECT - consistent structure
{
"status": "success",
"data": {
"user": {
"id": 123,
"name": "John Doe"
}
},
"meta": {
"timestamp": "2024-01-15T10:30:00Z",
"version": "1.0"
}
}
// CORRECT - error response
{
"status": "error",
"error": {
"code": "INVALID_INPUT",
"message": "Email address is required",
"field": "email"
}
}---
11. Pagination
// CORRECT - pagination metadata
{
"data": [
{"id": 1, "name": "Item 1"},
{"id": 2, "name": "Item 2"}
],
"pagination": {
"page": 1,
"pageSize": 20,
"totalPages": 5,
"totalItems": 100
}
}---
12. Versioning
// CORRECT - include version in response
{
"apiVersion": "2.0",
"data": {
"user": {
"id": 123,
"name": "John Doe"
}
}
}---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Trailing commas | Remove all trailing commas |
| Single quotes | Use double quotes only |
| Comments | JSON doesn't support comments |
| snake_case properties | Use camelCase |
| Undefined values | Use null or omit the property |
| Numbers as strings | Use actual number types |
| Inconsistent date formats | Use ISO 8601 |
MIT License
Copyright (c) 2026 TestDino
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.
Google Markdown Style Guide
Source: https://google.github.io/styleguide/docguide/style.html
Golden Rules
1. One sentence per line — for easier diffs and editing 2. ATX-style headers — use # not underlines 3. Fenced code blocks — use ` with language identifier 4. Reference-style links — for readability 5. Consistent list markers — * for unordered, 1. for ordered
---
1. Headers
<!-- CORRECT - ATX-style headers -->
# H1 Header
## H2 Header
### H3 Header
<!-- AVOID - Setext-style headers -->
H1 Header
=========
H2 Header
------------
2. Line Breaks
<!-- CORRECT - one sentence per line -->
This is the first sentence.
This is the second sentence.
This is the third sentence.
<!-- AVOID - multiple sentences on one line -->
This is the first sentence. This is the second sentence. This is the third sentence.---
3. Lists
<!-- CORRECT - unordered lists with * -->
* First item
* Second item
* Third item
<!-- CORRECT - ordered lists -->
1. First item
1. Second item
1. Third item
<!-- CORRECT - nested lists -->
* Parent item
* Child item
* Another child
* Another parent---
4. Code
<!-- CORRECT - inline code -->
Use the `print()` function to output text.
<!-- CORRECT - fenced code blocks with language -->def hello(): print("Hello, World!")
<!-- CORRECT - code block without language -->Plain text code block
<!-- AVOID - indented code blocks -->
def hello():
print("Hello")---
5. Links
<!-- CORRECT - inline links -->
Visit [Google](https://www.google.com) for search.
<!-- CORRECT - reference-style links (preferred for readability) -->
Visit [Google][google-link] for search.
Check out the [style guide][style-guide].
[google-link]: https://www.google.com
[style-guide]: https://google.github.io/styleguide/
<!-- CORRECT - automatic links -->
<https://www.google.com>---
6. Images
<!-- CORRECT - inline image -->

<!-- CORRECT - reference-style image -->
![Alt text][logo]
[logo]: image.png "Logo title"
<!-- CORRECT - image with link -->
[](https://www.google.com)---
7. Emphasis
<!-- CORRECT - italic -->
This is *italic* text.
This is _also italic_ text.
<!-- CORRECT - bold -->
This is **bold** text.
This is __also bold__ text.
<!-- CORRECT - bold and italic -->
This is ***bold and italic*** text.---
8. Tables
<!-- CORRECT - tables with alignment -->
| Name | Age | City |
|---------|----:|-----------|
| Alice | 30 | New York |
| Bob | 25 | London |
| Charlie | 35 | Tokyo |
<!-- Left-aligned | Right-aligned | Center-aligned -->
| Left | Right | Center |
|:-----|------:|:------:|
| A | 1 | X |
| B | 2 | Y |---
9. Blockquotes
<!-- CORRECT - blockquotes -->
> This is a blockquote.
> It can span multiple lines.
<!-- CORRECT - nested blockquotes -->
> This is a blockquote.
>
> > This is a nested blockquote.---
10. Horizontal Rules
<!-- CORRECT - horizontal rule -->
---
<!-- ALSO CORRECT -->
***
<!-- ALSO CORRECT -->
___---
11. Task Lists
<!-- CORRECT - task lists (GitHub-flavored) -->
- [x] Completed task
- [ ] Incomplete task
- [ ] Another incomplete task---
12. Escaping
<!-- CORRECT - escape special characters -->
Use \* for literal asterisks.
Use \# for literal hash marks.
Use \` for literal backticks.---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Multiple sentences per line | One sentence per line |
| Setext headers | Use ATX-style # headers |
| Indented code blocks | Use fenced code blocks with ` |
| No language in code blocks | Specify language: `python |
| Inconsistent list markers | Use * for unordered, 1. for ordered |
| Long inline links | Use reference-style links |
Google Objective-C Style Guide
Source: https://google.github.io/styleguide/objcguide.html
Golden Rules
1. Follow Apple's Cocoa Coding Guidelines — this guide extends them 2. Use descriptive names — clarity over brevity 3. 2-space indentation — no tabs 4. Prefix classes with 3+ characters — avoid naming collisions 5. Use ARC — Automatic Reference Counting for memory management 6. Document all public APIs — with clear comments
---
1. Naming
Classes and Protocols
// CORRECT - 3+ character prefix
@interface GTMExampleClass : NSObject
@end
@protocol GTMExampleDelegate <NSObject>
@end
// AVOID - no prefix or too short
@interface ExampleClass : NSObject // AVOID
@endMethods
// CORRECT - descriptive, reads like a sentence
- (void)addTarget:(id)target action:(SEL)action;
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;
// CORRECT - getter without 'get' prefix
- (NSString *)title;
- (BOOL)isEnabled;
// AVOID
- (NSString *)getTitle; // AVOID 'get' prefixVariables
// CORRECT - instance variables with underscore
@implementation MyClass {
NSString *_instanceVariable;
}
// CORRECT - local variables
NSString *localVariable;
int loopCounter;
// CORRECT - constants
static const NSTimeInterval kAnimationDuration = 0.3;---
2. File Structure
// MyClass.h
#import <Foundation/Foundation.h>
@class OtherClass;
/** Brief description of MyClass. */
@interface MyClass : NSObject
/** The main title. */
@property(nonatomic, copy) NSString *title;
/**
* Initializes with a title.
* @param title The title to use.
*/
- (instancetype)initWithTitle:(NSString *)title NS_DESIGNATED_INITIALIZER;
@end---
3. Properties
// CORRECT - property declarations
@property(nonatomic, copy) NSString *name;
@property(nonatomic, strong) UIView *contentView;
@property(nonatomic, weak) id<MyDelegate> delegate;
@property(nonatomic, assign) NSInteger count;
@property(nonatomic, readonly) BOOL isValid;
// CORRECT - use copy for NSString, NSArray, etc.
@property(nonatomic, copy) NSArray<NSString *> *items;---
4. Methods
// CORRECT - method implementation
- (instancetype)initWithTitle:(NSString *)title {
self = [super init];
if (self) {
_title = [title copy];
}
return self;
}
// CORRECT - method with multiple parameters
- (void)doSomethingWithString:(NSString *)string
number:(NSInteger)number
error:(NSError **)error {
// Implementation
}---
5. Control Flow
// CORRECT - braces on same line
if (condition) {
DoSomething();
} else {
DoSomethingElse();
}
// CORRECT - for loops
for (NSInteger i = 0; i < count; i++) {
Process(i);
}
// CORRECT - fast enumeration
for (NSString *item in array) {
Process(item);
}
// CORRECT - switch statements
switch (value) {
case 1:
DoSomething();
break;
case 2:
DoSomethingElse();
break;
default:
break;
}---
6. Blocks
// CORRECT - block as parameter
- (void)doAsyncWorkWithCompletion:(void (^)(NSError *error))completion {
dispatch_async(queue, ^{
// Work
completion(nil);
});
}
// CORRECT - block variable
void (^myBlock)(NSString *) = ^(NSString *input) {
NSLog(@"%@", input);
};---
7. Categories
// CORRECT - category naming
@interface NSString (GTMStringUtils)
- (NSString *)gtm_reversedString;
@end
// CORRECT - prefix methods to avoid collisions
@implementation NSString (GTMStringUtils)
- (NSString *)gtm_reversedString {
// Implementation
}
@end---
8. Protocols
// CORRECT - protocol definition
@protocol GTMDataSource <NSObject>
@required
- (NSInteger)numberOfItems;
- (id)itemAtIndex:(NSInteger)index;
@optional
- (NSString *)titleForItemAtIndex:(NSInteger)index;
@end---
9. Comments
/**
* A class representing a user profile.
* Use this class to manage user data and preferences.
*/
@interface GTMUserProfile : NSObject
/**
* The user's display name.
* This is shown in the UI and can be edited by the user.
*/
@property(nonatomic, copy) NSString *displayName;
/**
* Saves the profile to disk.
* @param error On failure, contains an error object.
* @return YES if successful, NO otherwise.
*/
- (BOOL)saveWithError:(NSError **)error;
@end---
10. Modern Objective-C
// CORRECT - use literals
NSArray *array = @[@"one", @"two", @"three"];
NSDictionary *dict = @{@"key": @"value"};
NSNumber *number = @42;
// CORRECT - use subscripting
NSString *item = array[0];
NSString *value = dict[@"key"];
// CORRECT - use generics
NSArray<NSString *> *strings;
NSDictionary<NSString *, NSNumber *> *mapping;---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| No class prefix | Use 3+ character prefix (e.g., GTM) |
get in getter names | Omit get prefix |
| Not using ARC | Use ARC for memory management |
| Retaining delegates | Use weak for delegates |
| Not copying NSString | Use copy for string properties |
| Missing nullability | Add nullable/nonnull annotations |
Google Python Style Guide
Source: https://google.github.io/styleguide/pyguide.html
Golden Rules
1. Follow PEP 8 as baseline — Google's guide extends it 2. Use type annotations for all public functions and methods 3. 4-space indentation — no tabs 4. Maximum line length: 80 characters 5. Docstrings mandatory for all public modules, functions, classes, methods 6. Prefer comprehensions over map()/filter() 7. Use f-strings for string formatting (Python 3.6+)
---
1. Imports
# CORRECT - stdlib, then third-party, then local
import os
import sys
from typing import Optional, List
import numpy as np
from myproject import utils
# INCORRECT
import os, sys # one import per line
from os.path import * # never wildcard imports---
2. Type Annotations
# CORRECT
def get_user(user_id: int) -> Optional[dict]:
...
def process_items(items: List[str], max_count: int = 10) -> List[str]:
...
# INCORRECT
def get_user(user_id): # add type annotations
...---
3. Docstrings (Google Style)
def fetch_data(url: str, timeout: int = 30) -> dict:
"""Fetches data from the given URL.
Args:
url: The URL to fetch data from.
timeout: Request timeout in seconds. Defaults to 30.
Returns:
A dictionary containing the response data.
Raises:
ValueError: If the URL is invalid.
"""
...---
4. Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Modules | snake_case | user_service.py |
| Classes | UpperCamelCase | UserService |
| Functions/Methods | snake_case | get_user_by_id |
| Variables | snake_case | user_count |
| Constants | UPPER_SNAKE_CASE | MAX_RETRIES |
| Protected | _single_leading | _internal |
| Private | __double_leading | __private |
---
5. Strings
# CORRECT - f-strings
name = "Alice"
greeting = f"Hello, {name}!"
# INCORRECT
greeting = "Hello, " + name + "!" # use f-strings
greeting = "Hello, %s!" % name # use f-strings---
6. Comprehensions
# CORRECT
squares = [x ** 2 for x in range(10)]
user_map = {user.id: user for user in users}
unique_names = {user.name for user in users}
evens = [x for x in range(20) if x % 2 == 0]
# INCORRECT
squares = list(map(lambda x: x ** 2, range(10))) # use comprehension---
7. Exception Handling
# CORRECT - catch specific exceptions
try:
data = json.loads(raw_input)
except json.JSONDecodeError as e:
raise ValueError(f"Could not parse: {e}") from e
# CORRECT - use context managers
with open("data.txt") as file:
content = file.read()
# INCORRECT
try:
...
except: # never bare except
pass---
8. Default Arguments
# INCORRECT - mutable default arguments
def add_item(item: str, items: List[str] = []) -> List[str]: # BAD!
items.append(item)
return items
# CORRECT - use None for mutable defaults
def add_item(item: str, items: Optional[List[str]] = None) -> List[str]:
if items is None:
items = []
items.append(item)
return items---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Mutable default args | Use None as default |
| Wildcard imports | Explicit imports only |
Bare except | Catch specific exceptions |
% or .format() strings | Use f-strings |
map()/filter() | Use comprehensions |
| Missing docstrings | Add Google-style docstrings |
| Missing type annotations | Annotate public functions |
Google R Style Guide
Source: https://google.github.io/styleguide/Rguide.html
Golden Rules
1. BigCamelCase for functions — to distinguish from objects 2. snake_case for variables — lowercase with underscores 3. Explicit `return()` — don't rely on implicit returns 4. Qualify namespaces — use package::function() 5. No `attach()` — avoid namespace pollution 6. No right-hand assignment — use <- on left only
---
1. Naming
| Element | Convention | Example |
|---|---|---|
| Functions | BigCamelCase | CalculateAverage() |
| Private functions | .BigCamelCase | .HelperFunction() |
| Variables | snake_case | user_count |
| Constants | snake_case | max_iterations |
# CORRECT - function naming
CalculateAverage <- function(x) {
return(mean(x, na.rm = TRUE))
}
# CORRECT - private function
.ValidateInput <- function(x) {
return(is.numeric(x))
}
# CORRECT - variable naming
user_count <- 10
total_sales <- sum(sales_data$amount)---
2. Assignment
# CORRECT - use <- for assignment
x <- 5
result <- CalculateTotal(data)
# AVOID - right-hand assignment
data %>%
filter(active == TRUE) -> filtered_data # AVOID
# AVOID - = for assignment (use for function arguments only)
x = 5 # AVOID---
3. Functions
# CORRECT - explicit return
CalculateTotal <- function(values) {
total <- sum(values, na.rm = TRUE)
return(total)
}
# AVOID - implicit return
CalculateTotal <- function(values) {
sum(values, na.rm = TRUE) # AVOID
}
# CORRECT - function with multiple returns
CheckValue <- function(x) {
if (x < 0) {
return("negative")
}
if (x == 0) {
return("zero")
}
return("positive")
}---
4. Namespace Qualification
# CORRECT - explicit namespace
result <- dplyr::filter(data, active == TRUE)
plot <- ggplot2::ggplot(data, ggplot2::aes(x, y))
# AVOID - importing everything
library(dplyr) # AVOID in packages
filter(data, active == TRUE)
# CORRECT - in package DESCRIPTION, use Imports not Depends---
5. Pipes
# CORRECT - pipe usage
result <- data %>%
dplyr::filter(active == TRUE) %>%
dplyr::group_by(category) %>%
dplyr::summarize(total = sum(amount))
# CORRECT - line breaks in pipes
result <- data %>%
dplyr::filter(
active == TRUE,
amount > 100
) %>%
dplyr::arrange(desc(amount))---
6. Data Manipulation
# CORRECT - dplyr for data manipulation
filtered_data <- data %>%
dplyr::filter(year == 2024) %>%
dplyr::select(id, name, amount) %>%
dplyr::mutate(
amount_usd = amount * exchange_rate,
category = dplyr::case_when(
amount < 100 ~ "small",
amount < 1000 ~ "medium",
TRUE ~ "large"
)
)---
7. Control Flow
# CORRECT - if/else
if (condition) {
DoSomething()
} else if (other_condition) {
DoSomethingElse()
} else {
DoDefault()
}
# CORRECT - for loop
for (i in seq_along(items)) {
ProcessItem(items[[i]])
}
# CORRECT - while loop
while (condition) {
DoSomething()
condition <- CheckCondition()
}---
8. Documentation
#' Calculate the average of a numeric vector
#'
#' This function calculates the mean of a numeric vector,
#' removing NA values by default.
#'
#' @param x A numeric vector
#' @param na_rm Logical, whether to remove NA values
#' @return The mean of x
#' @examples
#' CalculateAverage(c(1, 2, 3, 4, 5))
#' CalculateAverage(c(1, 2, NA, 4), na_rm = TRUE)
#' @export
CalculateAverage <- function(x, na_rm = TRUE) {
if (!is.numeric(x)) {
stop("x must be numeric")
}
return(mean(x, na.rm = na_rm))
}---
9. Package Development
# CORRECT - package structure
# R/
# calculate.R
# validate.R
# tests/
# testthat/
# test-calculate.R
# DESCRIPTION
# NAMESPACE
# CORRECT - in DESCRIPTION file
Imports:
dplyr,
ggplot2,
purrr
# CORRECT - in NAMESPACE (via roxygen2)
#' @importFrom dplyr filter mutate
#' @importFrom ggplot2 ggplot aes---
10. Testing
# CORRECT - testthat tests
test_that("CalculateAverage returns correct mean", {
result <- CalculateAverage(c(1, 2, 3, 4, 5))
expect_equal(result, 3)
})
test_that("CalculateAverage handles NA values", {
result <- CalculateAverage(c(1, 2, NA, 4), na_rm = TRUE)
expect_equal(result, 7/3)
})
test_that("CalculateAverage errors on non-numeric input", {
expect_error(
CalculateAverage(c("a", "b", "c")),
"x must be numeric"
)
})---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
Right-hand assignment -> | Use left-hand <- |
| Implicit returns | Use explicit return() |
Using attach() | Access data frame columns directly |
| Missing namespace | Use package::function() |
= for assignment | Use <- (save = for arguments) |
| Importing all functions | Import specific functions only |
Google Style Guides Skill for AI Coding Agents
<div align="center"> <p>Official Google style guides packaged as AI coding agent skills.</p> </div>
<div align="center"> <a href="https://github.com/testdino-hq/google-styleguides/stargazers"> <img src="https://img.shields.io/github/stars/testdino-hq/google-styleguides?style=social" alt="GitHub Stars"> </a> <a href="LICENSE"> <img src="https://img.shields.io/badge/license-CC--By%203.0-blue" alt="License"> </a> <img src="https://img.shields.io/badge/languages-17-green" alt="17 Languages"> </div>
---
Give your AI coding agent — Cursor, Claude, GitHub Copilot, Windsurf, or any AI tool — instant access to Google's battle-tested style guides. These aren't just docs; they're production-ready coding standards used across Google's engineering organization.
17 language style guides covering TypeScript, Python, JavaScript, Java, C++, Go, Swift, and more — formatted for AI agent consumption.
---
Table of Contents
- Who Is This For?
- Why These Style Guides?
- Quick Start
- Available Style Guides
- How It Works
- Contributing
- License
---
Who Is This For?
- Developers using AI coding agents who want consistent, Google-standard code generation
- Teams adopting Google's style guides across their codebase
- Anyone tired of inconsistent AI-generated code that doesn't follow best practices
- Engineering managers enforcing coding standards
---
Why These Style Guides?
AI agents generate code that works but often violates style conventions. Wrong naming, inconsistent formatting, anti-patterns — the same issues, over and over.
These guides package Google's official style guides in a format AI agents can reference during code generation. The result: code that follows industry-standard conventions from the first keystroke.
Source: https://google.github.io/styleguide/
---
Quick Start
The skills CLI copies style guide content into your project so AI coding agents can reference these standards when generating code.
Install All Style Guides
npx skills add testdino-hq/google-styleguides-skillsInstall Individual Style Guides
Pick only the languages you need:
# Frontend
npx skills add testdino-hq/google-styleguides-skills/typescript
npx skills add testdino-hq/google-styleguides-skills/javascript
npx skills add testdino-hq/google-styleguides-skills/html-css
npx skills add testdino-hq/google-styleguides-skills/angularjs
# Backend
npx skills add testdino-hq/google-styleguides-skills/python
npx skills add testdino-hq/google-styleguides-skills/java
npx skills add testdino-hq/google-styleguides-skills/go
npx skills add testdino-hq/google-styleguides-skills/cpp
npx skills add testdino-hq/google-styleguides-skills/csharp
# Mobile
npx skills add testdino-hq/google-styleguides-skills/swift
npx skills add testdino-hq/google-styleguides-skills/objective-c
# Other
npx skills add testdino-hq/google-styleguides-skills/shell
npx skills add testdino-hq/google-styleguides-skills/r
npx skills add testdino-hq/google-styleguides-skills/common-lisp
npx skills add testdino-hq/google-styleguides-skills/vim-script
npx skills add testdino-hq/google-styleguides-skills/json
npx skills add testdino-hq/google-styleguides-skills/markdown---
Available Style Guides
| Language | Command | What's Covered |
|---|---|---|
| TypeScript | npx skills add testdino-hq/google-styleguides-skills/typescript | Types, interfaces, naming, null handling, enums, imports |
| JavaScript | npx skills add testdino-hq/google-styleguides-skills/javascript | ES6+, modules, naming, formatting, JSDoc |
| Python | npx skills add testdino-hq/google-styleguides-skills/python | PEP 8, type hints, docstrings, imports, comprehensions |
| Java | npx skills add testdino-hq/google-styleguides-skills/java | Naming, formatting, Javadoc, exceptions, best practices |
| C++ | npx skills add testdino-hq/google-styleguides-skills/cpp | Headers, naming, formatting, classes, memory management |
| Go | npx skills add testdino-hq/google-styleguides-skills/go | Formatting, naming, comments, error handling, concurrency |
| Swift | npx skills add testdino-hq/google-styleguides-skills/swift | Naming, optionals, protocols, error handling, formatting |
| Objective-C | npx skills add testdino-hq/google-styleguides-skills/objective-c | Naming, formatting, memory management, protocols |
| C# | npx skills add testdino-hq/google-styleguides-skills/csharp | Naming, formatting, LINQ, async/await, XML docs |
| HTML/CSS | npx skills add testdino-hq/google-styleguides-skills/html-css | Formatting, naming, semantics, accessibility |
| AngularJS | npx skills add testdino-hq/google-styleguides-skills/angularjs | Controllers, services, directives, modules |
| Shell | npx skills add testdino-hq/google-styleguides-skills/shell | Bash scripting, naming, error handling, portability |
| R | npx skills add testdino-hq/google-styleguides-skills/r | Naming, formatting, functions, documentation |
| Common Lisp | npx skills add testdino-hq/google-styleguides-skills/common-lisp | Naming, formatting, macros, documentation |
| Vim Script | npx skills add testdino-hq/google-styleguides-skills/vim-script | Plugin structure, naming, portability |
| JSON | npx skills add testdino-hq/google-styleguides-skills/json | Formatting, naming, structure, comments |
| Markdown | npx skills add testdino-hq/google-styleguides-skills/markdown | Formatting, structure, links, lists |
---
How It Works
1. Install the skill using npx skills add 2. The style guide is copied to your project's .kiro/skills/ directory 3. Your AI agent reads it when generating code in that language 4. Generated code follows Google's style conventions automatically
The skills system integrates with:
- Cursor
- Claude
- GitHub Copilot
- Windsurf
- Any AI coding tool that supports context injection
---
Example: TypeScript
Before installing the skill:
// AI-generated code without style guide
function getUser(id) {
const user = users.find(u => u.id === id)!;
return user;
}After installing testdino-hq/google-styleguides-skills/typescript:
// AI-generated code following Google TypeScript style
function getUser(id: number): User | undefined {
return users.find(u => u.id === id);
}---
Language-Specific Quick Reference
TypeScript
- Use
strictmode - Prefer interfaces over type aliases for objects
- Never use
any— useunknown - Explicit return types on public functions
- No non-null assertions (
!)
Python
- Follow PEP 8
- Type annotations on all public functions
- Google-style docstrings
- f-strings for formatting
- Comprehensions over
map()/filter()
JavaScript
- Use
constby default - Arrow functions for callbacks
- Template literals for strings
- Destructuring where appropriate
- JSDoc for public APIs
Java
- UpperCamelCase for classes
- lowerCamelCase for methods
- Javadoc for public APIs
- Avoid wildcard imports
- Use Optional for nullable returns
Go
- Run
gofmtbefore commit - Short variable names in small scopes
- Error handling, not exceptions
- Interfaces for abstraction
- Defer for cleanup
---
Contributing
These guides are derived from Google's official style guides.
About External Contributions: With few exceptions, these style guides are copies of Google's internal style guides to assist developers working on Google-owned and originated open-source projects. Changes to the style guides are made to the internal style guides first and eventually copied into the versions found here.
How to Contribute:
- Issues: You can file issues using the GitHub tracker. Issues that raise questions, justify changes on technical merits, or point out obvious mistakes may get engagement.
- Content Updates: If you notice the content is outdated compared to the official Google style guides, please open an issue.
- Formatting Improvements: Suggestions for better AI agent consumption are welcome.
Note: We are primarily optimizing for accurate representation of Google's style guides and effective AI agent integration.
---
License
This project is licensed under the MIT License.
Copyright (c) 2026 TestDino
See LICENSE for full details.
---
<div align="center"> Built by <a href="https://testdino.com">TestDino</a> — production-grade code generation </div>
Google Shell Style Guide
Source: https://google.github.io/styleguide/shellguide.html
Golden Rules
1. Use Bash — #!/bin/bash for all shell scripts 2. 2-space indentation — no tabs 3. 80-character line limit — for readability 4. Quote variables — always use "${var}" 5. Check return values — never ignore errors 6. Use ShellCheck — lint your scripts 7. Keep scripts under 100 lines — or rewrite in another language
---
1. File Structure
#!/bin/bash
#
# Brief description of script purpose.
# Detailed usage information if needed.
set -euo pipefail # Exit on error, undefined vars, pipe failures
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly CONST_VALUE="constant"
main() {
# Main script logic here
do_something "$@"
}
do_something() {
local arg="$1"
echo "Processing: ${arg}"
}
main "$@"---
2. Naming
| Element | Convention | Example |
|---|---|---|
| Files | snake_case.sh | backup_database.sh |
| Functions | snake_case | do_something() |
| Variables | snake_case | file_name |
| Constants | UPPER_SNAKE_CASE | MAX_RETRIES |
| Environment vars | UPPER_SNAKE_CASE | PATH |
---
3. Functions
# CORRECT - function with comments
#######################################
# Cleanup files from backup directory.
# Globals:
# BACKUP_DIR
# Arguments:
# None
# Returns:
# 0 on success, 1 on error
#######################################
cleanup() {
local file
for file in "${BACKUP_DIR}"/*; do
rm "${file}" || return 1
done
return 0
}
# CORRECT - function call
cleanup || {
echo "Cleanup failed" >&2
exit 1
}---
4. Variables
# CORRECT - always quote variables
echo "${my_var}"
echo "${1}"
echo "${file_name}"
# CORRECT - use local in functions
my_function() {
local local_var="value"
echo "${local_var}"
}
# CORRECT - readonly for constants
readonly MAX_RETRIES=3
readonly CONFIG_FILE="/etc/myapp.conf"
# AVOID - unquoted variables
echo $my_var # AVOID
echo $1 # AVOID---
5. Conditionals
# CORRECT - use [[ ]] for tests
if [[ -f "${file}" ]]; then
echo "File exists"
fi
if [[ "${var}" == "value" ]]; then
do_something
fi
if [[ -z "${var}" ]]; then
echo "Variable is empty"
fi
# CORRECT - numeric comparisons
if (( count > 10 )); then
echo "Count is greater than 10"
fi
# AVOID - use [ ] (old test command)
if [ -f "${file}" ]; then # Use [[ ]] instead
echo "File exists"
fi---
6. Loops
# CORRECT - iterate over array
for item in "${array[@]}"; do
process "${item}"
done
# CORRECT - C-style for loop
for (( i = 0; i < 10; i++ )); do
echo "${i}"
done
# CORRECT - while loop
while read -r line; do
echo "Line: ${line}"
done < "${file}"
# CORRECT - process substitution (not pipe to while)
while read -r line; do
echo "${line}"
done < <(command)---
7. Error Handling
# CORRECT - check return values
if ! command; then
echo "Command failed" >&2
exit 1
fi
# CORRECT - use || for error handling
command || {
echo "Command failed" >&2
exit 1
}
# CORRECT - check $?
command
if (( $? != 0 )); then
echo "Command failed" >&2
exit 1
fi
# CORRECT - set options for safety
set -e # Exit on error
set -u # Exit on undefined variable
set -o pipefail # Exit on pipe failure---
8. Command Substitution
# CORRECT - use $() not backticks
result="$(command)"
files="$(ls -1)"
# AVOID - backticks
result=`command` # AVOID---
9. Arrays
# CORRECT - declare and use arrays
declare -a files
files=("file1.txt" "file2.txt" "file3.txt")
# CORRECT - append to array
files+=("file4.txt")
# CORRECT - iterate over array
for file in "${files[@]}"; do
echo "${file}"
done
# CORRECT - array length
echo "Array has ${#files[@]} elements"---
10. Pipes and Redirection
# CORRECT - pipe to while with process substitution
while read -r line; do
process "${line}"
done < <(command)
# CORRECT - redirect stderr
command 2>&1 | tee log.txt
# CORRECT - redirect to file
echo "output" > file.txt
echo "append" >> file.txt
# CORRECT - here document
cat <<EOF
Line 1
Line 2
EOF---
11. Case Statements
# CORRECT - case statement
case "${option}" in
start)
start_service
;;
stop)
stop_service
;;
restart)
stop_service
start_service
;;
*)
echo "Unknown option: ${option}" >&2
exit 1
;;
esac---
12. Best Practices
# CORRECT - use set for safety
set -euo pipefail
# CORRECT - use readonly for constants
readonly CONFIG_DIR="/etc/myapp"
# CORRECT - use local for function variables
my_func() {
local temp_file
temp_file="$(mktemp)"
# Use temp_file
}
# CORRECT - use shellcheck
# shellcheck disable=SC2034 # Unused variable
unused_var="value"
# CORRECT - use meaningful variable names
user_count=10 # GOOD
uc=10 # AVOID---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
| Unquoted variables | Always quote: "${var}" |
Using [ ] | Use [[ ]] instead |
| Backticks | Use $() for command substitution |
| Ignoring errors | Check return values with if ! or ` |
| Global variables | Use local in functions |
| Pipe to while | Use process substitution: < <(cmd) |
Missing set -e | Add safety options at top of script |
Google Swift Style Guide
Source: https://google.github.io/styleguide/swift.html
Golden Rules
1. Follow Apple's Swift API Design Guidelines — as baseline 2. 2-space indentation — no tabs 3. 100-character line limit — for readability 4. Use `let` over `var` — prefer immutability 5. Explicit `self` only when required — by compiler 6. Use type inference — when type is clear
---
1. Naming
| Element | Convention | Example |
|---|---|---|
| Types | UpperCamelCase | UserService, NetworkManager |
| Functions/Methods | lowerCamelCase | fetchUser(), calculateTotal() |
| Variables/Properties | lowerCamelCase | userName, isActive |
| Constants | lowerCamelCase | maxRetries, defaultTimeout |
| Enums | UpperCamelCase | Status, NetworkError |
| Enum cases | lowerCamelCase | .active, .inactive |
---
2. Types
// CORRECT - struct for value types
struct User {
let id: Int
let name: String
var email: String
}
// CORRECT - class for reference types
class UserService {
private let repository: UserRepository
init(repository: UserRepository) {
self.repository = repository
}
func fetchUser(id: Int) -> User? {
return repository.find(id: id)
}
}
// CORRECT - enum with associated values
enum Result<T> {
case success(T)
case failure(Error)
}---
3. Properties
// CORRECT - computed property
var fullName: String {
return "\(firstName) \(lastName)"
}
// CORRECT - property observer
var temperature: Double {
didSet {
if temperature > maxTemperature {
triggerAlert()
}
}
}
// CORRECT - lazy property
lazy var expensiveResource: Resource = {
return Resource()
}()---
4. Functions
// CORRECT - function with parameters
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
// CORRECT - function with default parameters
func connect(timeout: TimeInterval = 30) {
// Implementation
}
// CORRECT - function with closure parameter
func performAsync(completion: @escaping (Result<Data>) -> Void) {
// Implementation
}---
5. Optionals
// CORRECT - optional binding
if let user = optionalUser {
print(user.name)
}
// CORRECT - guard for early exit
guard let user = optionalUser else {
return
}
// CORRECT - optional chaining
let length = user?.name?.count
// CORRECT - nil-coalescing
let name = user?.name ?? "Unknown"
// AVOID - force unwrapping
let name = user!.name // AVOID unless absolutely certain---
6. Error Handling
// CORRECT - throwing function
enum NetworkError: Error {
case invalidURL
case noData
case decodingFailed
}
func fetchData(from url: String) throws -> Data {
guard let url = URL(string: url) else {
throw NetworkError.invalidURL
}
// Fetch data
return data
}
// CORRECT - do-catch
do {
let data = try fetchData(from: urlString)
process(data)
} catch NetworkError.invalidURL {
print("Invalid URL")
} catch {
print("Error: \(error)")
}
// CORRECT - try? for optional result
let data = try? fetchData(from: urlString)---
7. Closures
// CORRECT - trailing closure syntax
users.filter { $0.isActive }
.map { $0.name }
.sorted()
// CORRECT - explicit parameter names when needed
users.filter { user in
user.age > 18 && user.isActive
}
// CORRECT - capture list
someMethod { [weak self] result in
guard let self = self else { return }
self.handleResult(result)
}---
8. Control Flow
// CORRECT - if statement
if condition {
doSomething()
} else {
doSomethingElse()
}
// CORRECT - switch with pattern matching
switch result {
case .success(let data):
process(data)
case .failure(let error):
handle(error)
}
// CORRECT - for-in loop
for user in users {
print(user.name)
}
// CORRECT - while loop
while condition {
doSomething()
}---
9. Extensions
// CORRECT - organize code with extensions
extension User {
var displayName: String {
return "\(firstName) \(lastName)"
}
func isAdult() -> Bool {
return age >= 18
}
}
// CORRECT - protocol conformance in extension
extension User: Codable {}
extension User: Equatable {
static func == (lhs: User, rhs: User) -> Bool {
return lhs.id == rhs.id
}
}---
10. Protocols
// CORRECT - protocol definition
protocol UserRepository {
func find(id: Int) -> User?
func save(_ user: User)
}
// CORRECT - protocol with associated type
protocol Container {
associatedtype Item
func add(_ item: Item)
func get(at index: Int) -> Item?
}---
11. Generics
// CORRECT - generic function
func swap<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
// CORRECT - generic type
struct Stack<Element> {
private var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element? {
return items.popLast()
}
}---
12. Access Control
// CORRECT - use appropriate access levels
public class UserService {
private let repository: UserRepository
internal var cacheEnabled = true
public init(repository: UserRepository) {
self.repository = repository
}
public func fetchUser(id: Int) -> User? {
return repository.find(id: id)
}
private func clearCache() {
// Implementation
}
}---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
Using var everywhere | Prefer let for immutability |
Force unwrapping ! | Use optional binding or guard |
Unnecessary self | Only use when required by compiler |
Not using weak in closures | Use [weak self] to avoid retain cycles |
| Ignoring errors | Handle with do-catch or try? |
| Overusing classes | Prefer structs for value types |
Google TypeScript Style Guide
Source: https://google.github.io/styleguide/tsguide.html
>
This guide is based on Google's internal TypeScript style guide. It provides comprehensive rules for writing consistent, maintainable TypeScript code.
Table of Contents
1. Introduction 2. Source File Basics 3. Source File Structure 4. Imports and Exports 5. Language Features 6. Type System 7. Naming 8. Comments and Documentation 9. Policies
---
Introduction
Terminology
This guide uses RFC 2119 terminology:
- must / must not - Required / Forbidden
- should / should not - Recommended / Discouraged (prefer/avoid)
- may - Optional
All examples are non-normative and illustrate the rules but are not the only valid way to write code.
---
Source File Basics
File Encoding
Source files must be encoded in UTF-8.
Whitespace Characters
- Only ASCII horizontal space (0x20) is allowed
- All other whitespace in strings must be escaped
- Use special escape sequences (
\',\",\\,\b,\f,\n,\r,\t,\v) instead of numeric escapes
// ✓ GOOD
const units = 'μs';
const output = '\ufeff' + content; // byte order mark with comment
// ✗ BAD
const units = '\u03bcs'; // Hard to read
const output = '\ufeff' + content; // No explanation---
Source File Structure
Files consist of the following, in order, separated by exactly one blank line:
1. Copyright information (if present) 2. @fileoverview JSDoc (if present) 3. Imports (if present) 4. The file's implementation
@fileoverview JSDoc
/**
* @fileoverview Description of file. Lorem ipsum dolor sit amet, consectetur
* adipiscing elit, sed do eiusmod tempor incididunt.
*/---
Imports and Exports
Import Types
Four variants of imports:
// Module import (namespace)
import * as foo from '...';
// Named import (destructuring)
import {SomeThing} from '...';
// Default import (only when required by external code)
import SomeThing from '...';
// Side-effect import (only for libraries with side effects)
import '...';Import Paths
- Use relative paths (
./foo) for files within the same project - Limit parent steps (
../../../) as they make structure hard to understand
import {Symbol1} from 'path/from/root';
import {Symbol2} from '../parent/file';
import {Symbol3} from './sibling';Namespace vs Named Imports
- Prefer named imports for frequently used symbols or symbols with clear names
- Prefer namespace imports when using many symbols from large APIs
// ✗ BAD: overlong import
import {Item as TableviewItem, Header as TableviewHeader,
Row as TableviewRow} from './tableview';
// ✓ GOOD: use namespace
import * as tableview from './tableview';
let item: tableview.Item|undefined;
// ✓ GOOD: named imports for common functions
import {describe, it, expect} from './testing';Exports
Always use named exports. Never use default exports.
// ✓ GOOD
export class Foo { ... }
export function bar() { ... }
export const BAZ = 1;
// ✗ BAD
export default class Foo { ... }Why no default exports?
- No canonical name (can be imported as anything)
- Harder to maintain
- Don't error when importing non-existent members
- Encourage putting everything in one object
Export Visibility
- Only export symbols used outside the module
- Minimize exported API surface
Mutable Exports
Do not use `export let`. Use explicit getter functions instead.
// ✗ BAD
export let foo = 3;
setTimeout(() => { foo = 4; }, 1000);
// ✓ GOOD
let foo = 3;
setTimeout(() => { foo = 4; }, 1000);
export function getFoo() { return foo; }Container Classes
Do not create container classes with static methods/properties for namespacing.
// ✗ BAD
export class Container {
static FOO = 1;
static bar() { return 1; }
}
// ✓ GOOD
export const FOO = 1;
export function bar() { return 1; }Import and Export Type
Use import type when importing symbols only as types:
import type {Foo} from './foo';
import {Bar} from './foo';
// Or inline
import {type Foo, Bar} from './foo';Use export type when re-exporting types:
export type {AnInterface} from './foo';Modules Not Namespaces
Do not use `namespace`. Use ES6 modules with import/export.
// ✗ BAD
namespace Rocket {
function launch() { ... }
}
// ✗ BAD
/// <reference path="..."/>
// ✗ BAD
import x = require('mydep');
// ✓ GOOD
import {launch} from './rocket';---
Language Features
Local Variable Declarations
Use `const` and `let`. Never use `var`.
// ✓ GOOD
const foo = otherValue; // Use if never reassigned
let bar = someValue; // Use if reassigned later
// ✗ BAD
var foo = someValue; // var has confusing function scopeVariables must not be used before their declaration.
One variable per declaration:
// ✓ GOOD
let a = 1;
let b = 2;
// ✗ BAD
let a = 1, b = 2;Array Literals
Do not use the `Array()` constructor:
// ✗ BAD
const a = new Array(2); // [undefined, undefined]
const b = new Array(2, 3); // [2, 3] - confusing!
// ✓ GOOD
const a = [2];
const b = [2, 3];
const c = [];
c.length = 2;
Array.from<number>({length: 5}).fill(0); // [0, 0, 0, 0, 0]Do not define properties on arrays. Use Map or Object instead.
Spread Syntax:
// ✓ GOOD
const foo = [1];
const foo2 = [...foo, 6, 7];
const foo3 = [5, ...foo];
// ✗ BAD
const bar = [5, ...(shouldUseFoo && foo)]; // might be undefinedArray Destructuring:
// ✓ GOOD
const [a, b, c, ...rest] = generateResults();
let [, b,, d] = someArray; // Skip unused elements
// ✓ GOOD - default values
function destructured([a = 4, b = 2] = []) { … }
// ✗ BAD
function badDestructuring([a, b] = [4, 2]) { … }Object Literals
Do not use the `Object()` constructor. Use object literals ({} or {a: 0}).
Iterating Objects:
Do not use unfiltered for...in:
// ✗ BAD
for (const x in someObj) {
// x could come from prototype chain!
}
// ✓ GOOD
for (const x in someObj) {
if (!someObj.hasOwnProperty(x)) continue;
// now x is definitely on someObj
}
// ✓ BETTER
for (const x of Object.keys(someObj)) { ... }
for (const [key, value] of Object.entries(someObj)) { ... }Spread Syntax:
// ✓ GOOD
const foo = {num: 1};
const foo2 = {...foo, num: 5}; // foo2.num === 5
const foo3 = {num: 5, ...foo}; // foo3.num === 1
// ✗ BAD
const bar = {num: 5, ...(shouldUseFoo && foo)}; // might be undefinedObject Destructuring:
// ✓ GOOD
interface Options {
num?: number;
str?: string;
}
function destructured({num, str = 'default'}: Options = {}) {}
// ✗ BAD - nested too deeply
function nestedTooDeeply({x: {num, str}}: {x: Options}) {}
// ✗ BAD - non-trivial default
function nontrivialDefault({num, str}: Options = {num: 42, str: 'default'}) {}Classes
Class Declarations:
Do not terminate with semicolons:
// ✓ GOOD
class Foo {
}
// ✗ BAD
class Foo {
};But statements with class expressions need semicolons:
// ✓ GOOD
export const Baz = class extends Bar {
method(): number { return this.x; }
};Method Declarations:
Do not use semicolons between methods:
// ✓ GOOD
class Foo {
doThing() {
console.log("A");
}
getOtherThing(): number {
return 4;
}
}
// ✗ BAD
class Foo {
doThing() {
console.log("A");
}; // unnecessary semicolon
}Static Methods:
- Avoid private static methods (prefer module-local functions)
- Do not rely on dynamic dispatch of static methods
- Avoid
thisin static contexts
Constructors:
Use parentheses even with no arguments:
// ✓ GOOD
const x = new Foo();
// ✗ BAD
const x = new Foo;Omit empty constructors or those that only call super():
// ✗ BAD - unnecessary
class UnnecessaryConstructor {
constructor() {}
}
// ✓ GOOD - has parameter properties
class ParameterProperties {
constructor(private myService) {}
}Class Members:
Do not use `#private` fields. Use TypeScript's private instead:
// ✗ BAD
class Clazz {
#ident = 1;
}
// ✓ GOOD
class Clazz {
private ident = 1;
}Use `readonly` for properties never reassigned:
class Foo {
private readonly barService: BarService;
constructor(barService: BarService) {
this.barService = barService;
}
}
// ✓ BETTER - parameter properties
class Foo {
constructor(private readonly barService: BarService) {}
}Field Initializers:
Initialize where declared when possible:
// ✗ BAD
class Foo {
private readonly userList: string[];
constructor() {
this.userList = [];
}
}
// ✓ GOOD
class Foo {
private readonly userList: string[] = [];
}Getters and Setters:
- Getters must be pure functions (no side effects)
- Use to restrict visibility of internal details
- At least one accessor must be non-trivial
// ✓ GOOD
class Foo {
private wrappedBar = '';
get bar() {
return this.wrappedBar || 'bar';
}
set bar(wrapped: string) {
this.wrappedBar = wrapped.trim();
}
}
// ✗ BAD - pass-through accessors
class Bar {
private barInternal = '';
get bar() { return this.barInternal; }
set bar(value: string) { this.barInternal = value; }
}Visibility:
- Limit visibility as much as possible
- Never use
publicmodifier except for non-readonly parameter properties - Consider converting private methods to non-exported functions
// ✗ BAD
class Foo {
public bar = new Bar();
constructor(public readonly baz: Baz) {}
}
// ✓ GOOD
class Foo {
bar = new Bar();
constructor(public baz: Baz) {}
}Functions
Prefer function declarations for named functions:
// ✓ GOOD
function foo() {
return 42;
}
// ✗ BAD
const foo = () => 42;Do not use function expressions. Use arrow functions:
// ✓ GOOD
bar(() => { this.doSomething(); })
// ✗ BAD
bar(function() { ... })Arrow Function Bodies:
Use concise bodies for expressions, block bodies otherwise:
// ✓ GOOD - concise body when return value used
const longThings = myValues.filter(v => v.length > 1000);
// ✓ GOOD - block body when return value unused
myPromise.then(v => {
console.log(v);
});
// ✗ BAD - concise body when return value unused
myPromise.then(v => console.log(v));Rebinding `this`:
Avoid rebinding this. Use arrow functions or explicit parameters:
// ✗ BAD
function clickHandler() {
this.textContent = 'Hello';
}
document.body.onclick = clickHandler;
// ✓ GOOD
document.body.onclick = () => {
document.body.textContent = 'hello';
};Arrow Functions as Properties:
Avoid arrow function properties in classes:
// ✗ BAD
class DelayHandler {
private patienceTracker = () => {
this.waitedPatiently = true;
}
}
// ✓ GOOD
class DelayHandler {
constructor() {
setTimeout(() => {
this.patienceTracker();
}, 5000);
}
private patienceTracker() {
this.waitedPatiently = true;
}
}Parameter Initializers:
Keep initializers simple with no side effects:
// ✓ GOOD
function process(name: string, extraContext: string[] = []) {}
function activate(index = 0) {}
// ✗ BAD - side effect
let globalCounter = 0;
function newId(index = globalCounter++) {}Rest and Spread:
Use rest parameters instead of arguments:
// ✓ GOOD
function variadic(array: string[], ...numbers: number[]) {}
// Use spread instead of Function.prototype.apply
myFunction(...array, ...iterable);Primitive Literals
String Literals:
Use single quotes (') for ordinary strings:
// ✓ GOOD
const greeting = 'Hello';
// ✗ BAD
const greeting = "Hello";No line continuations:
// ✗ BAD
const LONG_STRING = 'This is a very long string. \
It has problems.';
// ✓ GOOD
const LONG_STRING = 'This is a very long string. ' +
'It uses concatenation.';Template Literals:
Use template literals for complex concatenation:
// ✓ GOOD
function arithmetic(a: number, b: number) {
return `Here is a table:
${a} + ${b} = ${a + b}
${a} - ${b} = ${a - b}`;
}Number Literals:
Use 0x, 0o, 0b prefixes (lowercase) for hex, octal, binary.
Type Coercion
Use String(), Boolean(), !!, or template literals for coercion:
// ✓ GOOD
const bool = Boolean(false);
const str = String(aNumber);
const bool2 = !!str;
const str2 = `result: ${bool2}`;
// ✗ BAD
const str = '' + aNumber; // Don't use + for coercionEnum to Boolean:
Do not convert enums to booleans. Compare explicitly:
enum SupportLevel { NONE, BASIC, ADVANCED }
// ✗ BAD
const level: SupportLevel = ...;
let enabled = Boolean(level);
// ✓ GOOD
let enabled = level !== SupportLevel.NONE;Parsing Numbers:
Use Number() and check for NaN:
// ✓ GOOD
const aNumber = Number('123');
if (!isFinite(aNumber)) throw new Error(...);
// ✗ BAD
const x = +y; // Unary plus is easy to miss
const n = parseInt(someString, 10); // Ignores trailing charsControl Structures
Always use braces:
// ✓ GOOD
for (let i = 0; i < x; i++) {
doSomethingWith(i);
}
if (x) {
doSomething();
}
// ✗ BAD
if (x) doSomething();
for (let i = 0; i < x; i++) doSomethingWith(i);
// Exception: one-line if
if (x) x.doFoo();Iterating Containers:
Prefer for...of for arrays:
// ✓ GOOD
for (const x of someArr) {
// x is a value
}
for (const [i, x] of someArr.entries()) {
// i is index, x is value
}
// Also OK
for (let i = 0; i < someArr.length; i++) {
const x = someArr[i];
}Use for...in only for dict-style objects with hasOwnProperty check:
// ✓ GOOD
for (const key in obj) {
if (!obj.hasOwnProperty(key)) continue;
doWork(key, obj[key]);
}
// ✓ BETTER
for (const key of Object.keys(obj)) {
doWork(key, obj[key]);
}Exception Handling
Instantiate errors with `new`:
// ✓ GOOD
throw new Error('Foo is not valid');
// ✗ BAD
throw Error('Foo is not valid');Only throw errors:
// ✗ BAD
throw 'oh noes!';
Promise.reject('oh noes!');
// ✓ GOOD
throw new Error('oh noes!');
Promise.reject(new Error('oh noes!'));Empty catch blocks:
Explain why in a comment:
// ✓ GOOD
try {
return handleNumericResponse(response);
} catch (e: unknown) {
// Response is not numeric. Continue to handle as text.
}
return handleTextResponse(response);Switch Statements
Must contain a default (even if empty):
// ✓ GOOD
switch (x) {
case Y:
doSomething();
break;
default:
// nothing to do
}No fall-through (except empty cases):
// ✓ GOOD
switch (x) {
case X:
case Y:
doSomething();
break;
default:
}
// ✗ BAD
switch (x) {
case X:
doSomething();
// fall through - not allowed!
case Y:
doOther();
}Equality Checks
Always use `===` and `!==`:
// ✓ GOOD
if (foo === 'bar' || baz !== bam) { }
// ✗ BAD
if (foo == 'bar' || baz != bam) { }
// Exception: comparing to null
if (foo == null) {
// Matches both null and undefined
}Type Assertions
Avoid type assertions. They are unsafe and don't insert runtime checks.
// ✗ BAD
(x as Foo).foo();
y!.bar();
// ✓ GOOD - use runtime checks
if (x instanceof Foo) {
x.foo();
}
if (y) {
y.bar();
}If necessary, add a comment explaining why it's safe:
// x is a Foo because [reason]
(x as Foo).foo();Type assertion syntax:
Use as, not angle brackets:
// ✗ BAD
const x = (<Foo>z).length;
// ✓ GOOD
const x = (z as Foo).length;Object literals:
Use type annotations, not assertions:
interface Foo {
bar: number;
baz?: string;
}
// ✗ BAD
const foo = {
bar: 123,
bam: 'abc', // Typo not caught!
} as Foo;
// ✓ GOOD
const foo: Foo = {
bar: 123,
bam: 'abc', // Error: bam not on Foo
};---
Type System
Type Inference
Code may rely on type inference for all type expressions.
Leave out trivially inferred types:
// ✗ BAD
const x: boolean = true;
const y: Set<string> = new Set();
// ✓ GOOD
const x = true;
const y = new Set<string>(); // Generic needs explicit typeUse annotations for complex expressions:
// Hard to infer
const value = await rpc.getSomeValue().transform();
// ✓ BETTER
const value: string[] = await rpc.getSomeValue().transform();Return Types
Return type annotations are optional but recommended for:
- Public APIs
- Complex return types
- Preventing future type errors
// Optional but helpful
function add(a: number, b: number): number {
return a + b;
}Undefined and Null
- TypeScript supports both
undefinedandnull - No general preference for one over the other
- Use what the API expects (Map uses
undefined, DOM usesnull)
Nullable type aliases:
Do not include |null or |undefined in type aliases:
// ✗ BAD
type CoffeeResponse = Latte|Americano|undefined;
class CoffeeService {
getLatte(): CoffeeResponse { ... }
}
// ✓ GOOD
type CoffeeResponse = Latte|Americano;
class CoffeeService {
getLatte(): CoffeeResponse|undefined { ... }
}Prefer optional over `|undefined`:
// ✓ GOOD
interface CoffeeOrder {
sugarCubes: number;
milk?: Whole|LowFat; // Optional, not |undefined
}
function pourCoffee(volume?: Milliliter) { ... }Structural Types
TypeScript uses structural typing (not nominal).
Use interfaces for structural types:
// ✓ GOOD
interface Foo {
a: number;
b: string;
}
const foo: Foo = {
a: 123,
b: 'abc',
};
// ✗ BAD - relies on inference
const badFoo = {
a: 123,
b: 'abc',
};Prefer interfaces over type literals:
// ✓ GOOD
interface User {
firstName: string;
lastName: string;
}
// ✗ BAD
type User = {
firstName: string,
lastName: string,
}Array<T> Type
Use `T[]` for simple types:
// ✓ GOOD
let a: string[];
let b: readonly string[];
let c: ns.MyObj[];
let d: string[][];
// ✗ BAD
let a: Array<string>;
let b: ReadonlyArray<string>;Use `Array<T>` for complex types:
// ✓ GOOD
let e: Array<{n: number, s: string}>;
let f: Array<string|number>;
let g: ReadonlyArray<string|number>;Indexable Types
Use for associative arrays, but consider Map or Set instead:
// OK but consider Map
const fileSizes: {[fileName: string]: number} = {};
fileSizes['readme.txt'] = 541;
// ✓ BETTER - use meaningful labels
const users: {[userName: string]: number} = {};
// ✓ BEST - use Map
const users = new Map<string, number>();Mapped and Conditional Types
Use sparingly. They can make code hard to understand:
// Consider if this is clearer than explicit interfaces
type FoodPreferences = Pick<User, 'favoriteIcecream'|'favoriteChocolate'>;
// Often better to be explicit
interface FoodPreferences {
favoriteIcecream: string;
favoriteChocolate: string;
}any Type
Avoid `any`. Consider alternatives:
1. Provide a more specific type:
// ✓ GOOD
interface MyUserJson {
name: string;
email: string;
}
type MyType = number|string;2. Use `unknown`:
// ✓ GOOD
const val: unknown = value;
if (typeof val === 'string') {
// Now can use as string
}
// ✗ BAD
const danger: any = value;
danger.whoops(); // Unchecked!3. Suppress with comment:
// This test only needs partial BookService
// tslint:disable-next-line:no-any
const mockBookService = ({get() { return mockBook; }} as any) as BookService;{} Type
Avoid `{}` type. Use instead:
unknown- for any value including null/undefinedRecord<string, T>- for dictionary-like objectsobject- excludes primitives
Tuple Types
Use tuples instead of Pair interfaces:
// ✗ BAD
interface Pair {
first: string;
second: string;
}
// ✓ GOOD
function splitInHalf(input: string): [string, string] {
return [x, y];
}
const [leftHalf, rightHalf] = splitInHalf('my string');For clarity, consider inline object types:
function splitHostPort(address: string): {host: string, port: number} {
...
}
const {host, port} = splitHostPort(userAddress);Wrapper Types
Never use wrapper types String, Boolean, Number, Object.
// ✗ BAD
const s = new String('hello');
const b = new Boolean(false);
// ✓ GOOD
const s: string = 'hello';
const b: boolean = false;Always use lowercase string, boolean, number, object.
---
Naming
Identifiers
Use only ASCII letters, digits, underscores (for constants and test names), and rarely $.
Naming Style
Do not decorate names with type information:
- No trailing/leading underscores for private (use
privatekeyword) - No
opt_prefix for optional parameters - No
Iprefix for interfaces (unless idiomatic) - Observables may use
$suffix (team decision)
Descriptive Names
Names must be clear to new readers:
// ✓ GOOD
errorCount
dnsConnectionIndex
referrerUrl
customerId
// ✗ BAD
n // Meaningless
nErr // Ambiguous
wgcConnections // Only your group knows
cstmrId // Deletes letters
kSecondsPerDay // Hungarian notation
customerID // Wrong camelCaseCamel Case
Treat abbreviations as whole words:
// ✓ GOOD
loadHttpUrl
XMLHttpRequest // Platform name exception
// ✗ BAD
loadHTTPURLRules by Identifier Type
| Style | Category |
|---|---|
| UpperCamelCase | class, interface, type, enum, decorator, type parameters |
| lowerCamelCase | variable, parameter, function, method, property, module alias |
| CONSTANT_CASE | global constant values, enum values |
| #ident | Never use private identifiers |
Constants
Use CONSTANT_CASE for:
- Module-level constants
- Static readonly class properties
- Enum values
const UNIT_SUFFIXES = {
'milliseconds': 'ms',
'seconds': 's',
};
class Foo {
private static readonly MY_SPECIAL_NUMBER = 5;
}Not for local variables:
// ✗ BAD - local variable
function foo() {
const SOME_CONSTANT = 5; // Use lowerCamelCase
}Aliases
Match the format of the source:
const {BrewStateEnum} = SomeType;
const CAPACITY = 5;
class Teapot {
readonly BrewStateEnum = BrewStateEnum;
readonly CAPACITY = CAPACITY;
}---
Comments and Documentation
Comment Types
/** JSDoc */- For documentation (users of the code)//- For implementation (only for code maintainers)
JSDoc General Form
/**
* Multiple lines of JSDoc text are written here,
* wrapped normally.
* @param arg A number to do something to.
*/
function doSomething(arg: number) { … }
/** This short jsdoc describes the function. */
function doSomething(arg: number) { … }Markdown in JSDoc
JSDoc is written in Markdown:
/**
* Computes weight based on three factors:
*
* - items sent
* - items received
* - last timestamp
*/JSDoc Tags
Most tags must occupy their own line:
// ✓ GOOD
/**
* @param left A description of the left param.
* @param right A description of the right param.
*/
function add(left: number, right: number) { ... }
// ✗ BAD
/**
* @param left @param right
*/
function add(left: number, right: number) { ... }Document Top-Level Exports
Use JSDoc for all exported symbols:
/** Component that prints "bar". */
@Component({
selector: 'foo',
template: 'bar',
})
export class FooComponent {}Method and Function Comments
- Omit if obvious from name and signature
- Start with verb phrase in third person
- Document parameter properties with
@param
/**
* POSTs the request to start coffee brewing.
* @param amountLitres The amount to brew. Must fit the pot size!
*/
brew(amountLitres: number, logger: Logger) { ... }Parameter Properties
/** This class demonstrates parameter properties. */
class ParamProps {
/**
* @param percolator The percolator used for brewing.
* @param beans The beans to brew.
*/
constructor(
private readonly percolator: Percolator,
private readonly beans: CoffeeBean[]) {}
}JSDoc Type Annotations
Do not use JSDoc type annotations in TypeScript:
// ✗ BAD - redundant
/**
* @param {number} amountLitres
* @return {boolean}
*/
brew(amountLitres: number): boolean { ... }
// ✓ GOOD
/**
* @param amountLitres The amount to brew.
*/
brew(amountLitres: number): boolean { ... }Parameter Name Comments
Use when parameter meaning isn't clear:
// ✓ GOOD
someFunction(obviousParam, /* shouldRender= */ true, /* name= */ 'hello');
// Consider refactoring to use an interface instead
interface Options {
shouldRender: boolean;
name: string;
}
someFunction(obviousParam, {shouldRender: true, name: 'hello'});---
Policies
Consistency
- Follow what the file already does
- New files must use Google Style
- When reformatting, do it in a separate change
Deprecation
Mark with @deprecated and provide clear migration path:
/**
* @deprecated Use newMethod() instead.
*/
oldMethod() { ... }Disallowed Features
Do not use:
- Wrapper objects for primitives (
new String(),new Boolean(),new Number()) const enum(use plainenum)- Debugger statements in production
withkeywordevalorFunction(...string)constructor- Non-standard features
- Modifying builtin objects
Automatic Semicolon Insertion
Do not rely on ASI. Always use explicit semicolons.
Toolchain
TypeScript Compiler:
- All code must pass type checking
- Do not use
@ts-ignore,@ts-expect-error, or@ts-nocheck - Exception:
@ts-expect-errorin unit tests (use sparingly)
---
Summary
This guide provides comprehensive rules for writing TypeScript code that is:
- Consistent - Follows established patterns
- Maintainable - Easy to understand and modify
- Type-safe - Leverages TypeScript's type system
- Scalable - Works well in large codebases
For the complete official guide with all details and rationale, see: https://google.github.io/styleguide/tsguide.html
---
Last Updated: Based on Google's official TypeScript Style Guide License: CC-By 3.0 (Google Inc.)
Google Vim Script Style Guide
Source: https://google.github.io/styleguide/vimscriptguide.xml
Golden Rules
1. Use 2-space indentation — for readability 2. Prefix plugin functions — with plugin name 3. Use `abort` on functions — for error handling 4. Prefer `scriptencoding utf-8` — at top of file 5. Use `l:` for local variables — explicit scoping 6. Document all functions — with comments
---
1. File Structure
" CORRECT - file header
" Plugin: MyPlugin
" Description: Does something useful
" Maintainer: Your Name <email@example.com>
" License: Apache 2.0
if exists('g:loaded_myplugin')
finish
endif
let g:loaded_myplugin = 1
scriptencoding utf-8
" Plugin code here---
2. Naming
| Element | Convention | Example |
|---|---|---|
| Functions | PrefixedCamelCase | myplugin#DoSomething() |
| Global vars | g:plugin_name | g:myplugin_enabled |
| Script vars | s:variable_name | s:internal_state |
| Local vars | l:variable_name | l:temp_value |
| Buffer vars | b:variable_name | b:current_mode |
" CORRECT - function naming
function! myplugin#ProcessBuffer() abort
let l:lines = getline(1, '$')
" Process lines
endfunction
" CORRECT - variable scoping
let g:myplugin_enabled = 1
let s:internal_counter = 0---
3. Functions
" CORRECT - function with abort
function! myplugin#CalculateTotal(numbers) abort
" Calculate sum of numbers
let l:total = 0
for l:num in a:numbers
let l:total += l:num
endfor
return l:total
endfunction
" CORRECT - function with range
function! myplugin#ProcessRange() range abort
for l:line_num in range(a:firstline, a:lastline)
let l:line = getline(l:line_num)
" Process line
endfor
endfunction
" CORRECT - function with optional arguments
function! myplugin#Greet(...) abort
let l:name = a:0 >= 1 ? a:1 : 'World'
echo 'Hello, ' . l:name . '!'
endfunction---
4. Variables
" CORRECT - explicit scoping
function! myplugin#Example() abort
let l:local_var = 'local'
let s:script_var = 'script'
let g:global_var = 'global'
" Use variables
echo l:local_var
endfunction
" CORRECT - checking if variable exists
if exists('g:myplugin_config')
let l:config = g:myplugin_config
else
let l:config = {}
endif---
5. Conditionals
" CORRECT - if statement
if condition
" Do something
elseif other_condition
" Do something else
else
" Default action
endif
" CORRECT - checking for features
if has('python3')
" Use Python 3
elseif has('python')
" Use Python 2
else
echoerr 'Python not available'
endif---
6. Loops
" CORRECT - for loop
for l:item in l:items
echo l:item
endfor
" CORRECT - while loop
let l:i = 0
while l:i < 10
echo l:i
let l:i += 1
endwhile
" CORRECT - iterating over range
for l:i in range(1, 10)
echo l:i
endfor---
7. Commands
" CORRECT - define custom command
command! -nargs=1 MyPluginGreet call myplugin#Greet(<f-args>)
" CORRECT - command with range
command! -range MyPluginProcess <line1>,<line2>call myplugin#ProcessRange()
" CORRECT - command with completion
command! -nargs=1 -complete=file MyPluginOpen call myplugin#Open(<f-args>)---
8. Mappings
" CORRECT - normal mode mapping
nnoremap <silent> <Leader>mp :call myplugin#Process()<CR>
" CORRECT - visual mode mapping
vnoremap <silent> <Leader>mp :call myplugin#ProcessSelection()<CR>
" CORRECT - insert mode mapping
inoremap <silent> <C-Space> <C-R>=myplugin#Complete()<CR>
" CORRECT - buffer-local mapping
nnoremap <buffer> <silent> <Leader>mp :call myplugin#ProcessBuffer()<CR>---
9. Autocommands
" CORRECT - autocommand group
augroup MyPlugin
autocmd!
autocmd BufRead,BufNewFile *.txt call myplugin#SetupTextFile()
autocmd FileType python call myplugin#SetupPython()
augroup END---
10. Error Handling
" CORRECT - try-catch
function! myplugin#SafeOperation() abort
try
" Risky operation
call myplugin#RiskyFunction()
catch /^Vim\%((\a\+)\)\=:E/
echoerr 'Operation failed: ' . v:exception
finally
" Cleanup
call myplugin#Cleanup()
endtry
endfunction
" CORRECT - checking for errors
if !executable('git')
echoerr 'Git not found'
finish
endif---
11. String Operations
" CORRECT - string concatenation
let l:message = 'Hello, ' . l:name . '!'
" CORRECT - string comparison
if l:str ==# 'exact' " Case-sensitive
echo 'Match'
endif
if l:str ==? 'case' " Case-insensitive
echo 'Match'
endif
" CORRECT - string functions
let l:upper = toupper(l:str)
let l:lower = tolower(l:str)
let l:trimmed = trim(l:str)---
12. Lists and Dictionaries
" CORRECT - lists
let l:items = ['apple', 'banana', 'cherry']
let l:first = l:items[0]
call add(l:items, 'date')
" CORRECT - dictionaries
let l:config = {
\ 'host': 'localhost',
\ 'port': 8080,
\ 'enabled': 1
\ }
let l:host = l:config['host']
let l:port = get(l:config, 'port', 80)---
Common Mistakes
| Mistake | Correct Approach |
|---|---|
Missing abort | Always use abort on functions |
| No variable scoping | Use l:, s:, g: prefixes |
| Global namespace pollution | Prefix functions with plugin name |
| Missing guard clause | Check g:loaded_plugin at top |
| No autocommand group | Wrap autocommands in augroup |
| Case-insensitive comparison | Use ==# or ==? explicitly |