TypeScript Style Guide
Rules ¶
Require that member overloads be consecutive ¶
@typescript-eslint/adjacent-overload-signatures
Grouping overloaded members together can improve readability of the code.
// Incorrect declare namespace Foo { export function foo(s: string): void export function foo(n: number): void export function bar(): void export function foo(sn: string | number): void } // Correct declare namespace Foo { export function foo(s: string): void export function foo(n: number): void export function foo(sn: string | number): void export function bar(): void }
Disallow awaiting a value that is not a Thenable ¶
@typescript-eslint/await-thenable
This rule disallows awaiting a value that is not a "Thenable" (an object which has then method, > such as a Promise). While it is valid JavaScript to await a non-Promise-like value (it will > resolve immediately), this pattern is often a programmer error, such as forgetting to add > parenthesis to call a function that returns a Promise.
// Incorrect await 'value' const createValue = () => 'value' await createValue() // Correct await Promise.resolve('value') const createValue = async () => 'value' await createValue()
Disallow @ts- comments or require descriptions after directive ¶
@typescript-eslint/ban-ts-comment
TypeScript provides several directive comments that can be used to alter how it processes files. Using these to suppress TypeScript Compiler Errors reduces the effectiveness of TypeScript overall.
https://typescript-eslint.io/rules/ban-ts-comment/
Disallow the declaration of empty interfaces ¶
@typescript-eslint/no-empty-interface
// Incorrect // an empty interface interface Foo {} // an interface with only one supertype (Bar === Foo) interface Bar extends Foo {} // an interface with an empty list of supertypes interface Baz {} // Correct interface Foo { name: string } // same as above interface Bar { age: number } // an interface with more than one supertype // in this case the interface can be used as a replacement of a union type. interface Baz extends Foo, Bar {}
Disallow the any type ¶
'@typescript-eslint/no-explicit-any': [ 'error', { fixToUnknown: false, ignoreRestArgs: true } ]
// Incorrect const age: any = 'seventeen'; const ages: any[] = ['seventeen']; function greet(param: Array<any>): Array<any> {} // Correct const age: number = 17; const ages: number[] = [17]; function greet(param: Array<string>): Array<string> {}
Disallow extra non-null assertion ¶
@typescript-eslint/no-extra-non-null-assertion
// Incorrect const foo: { bar: number } | null = null const bar = foo!!!.bar // Correct const foo: { bar: number } | null = null const bar = foo!.bar
Disallow iterating over an array with a for-in loop ¶
@typescript-eslint/no-for-in-array
A for-in loop (for (var k in o)) iterates over the properties of an Object. While it is legal to use for-in loops with array types, it is not common. for-in will iterate over the indices of the array as strings, omitting any "holes" in the array. More common is to use for-of, which iterates over the values of an array.
// Incorrect for (const x in [3, 4, 5]) { console.log(x) } // Correct for (const x in { a: 3, b: 4, c: 5 }) { console.log(x) }
Disallow explicit type declarations for variables or parameters initialized to a number, string, or boolean ¶
@typescript-eslint/no-inferrable-types
// Incorrect const a: bigint = 10n const a: bigint = -10n const a: bigint = BigInt(10) const a: bigint = -BigInt(10) const a: boolean = false const a: boolean = true // Correct const a = 10n const a = -10n const a = BigInt(10) const a = -BigInt(10) const a = false const a = true
Disallow non-null assertions after an optional chain expression ¶
@typescript-eslint/no-non-null-asserted-optional-chain
// Incorrect foo?.bar! foo?.bar()! foo?.bar!.baz foo?.bar!() foo?.bar!().baz // Correct foo?.bar (foo?.bar).baz foo?.bar() foo?.bar() foo?.bar().baz
Disallow returning a value with type any from a function ¶
@typescript-eslint/no-unsafe-return
// Incorrect function foo1() { return 1 as any } function foo2() { return Object.create(null) } // Correct function foo1() { return 1 } function foo2() { return Object.create(null) as Record<string, unknown> }
Disallow require statements except in import statements ¶
@typescript-eslint/no-var-requires
// Incorrect var foo = require('foo') const foo = require('foo') let foo = require('foo') // Correct import foo = require('foo') require('foo') import foo from 'foo'
Require using namespace keyword over module keyword to declare custom TypeScript modules ¶
@typescript-eslint/prefer-namespace-keyword
In an effort to prevent further confusion between custom TypeScript modules and the new ES2015 modules, starting with TypeScript v1.5 the keyword namespace is now the preferred way to declare custom TypeScript modules
Require both operands of addition to have type number or string ¶
@typescript-eslint/restrict-plus-operands
// Incorrect var foo = '5.5' + 5 var foo = 1n + 1 // Correct var foo = parseInt('5.5', 10) + 10 var foo = 1n + 1n
Enforce template literal expressions to be of string type ¶
@typescript-eslint/restrict-template-expressions
// Incorrect const arg1 = [1, 2] const msg1 = `arg1 = ${arg1}` const arg2 = { name: 'Foo' } const msg2 = `arg2 = ${arg2 || null}` // Correct const arg = 'foo' const msg1 = `arg = ${arg}` const msg2 = `arg = ${arg || 'default'}` const stringWithKindProp: string & { _kind?: 'MyString' } = 'foo' const msg3 = `stringWithKindProp = ${stringWithKindProp}`
Setting in project ¶
If there is .eslintrc.{js,yml,json} in your project, you can add '@vue/eslint-config-typescript' as extension.
extends: ['@vue/eslint-config-typescript']
Then, add some lints in rules.
'@typescript-eslint/adjacent-overload-signatures': 'error', '@typescript-eslint/ban-ts-comment': [ 'error', { 'ts-expect-error': 'allow-with-description', 'ts-ignore': true, 'ts-nocheck': true, 'ts-check': false, minimumDescriptionLength: 3 } ], '@typescript-eslint/no-empty-interface': 'error', '@typescript-eslint/no-explicit-any': [ 'error', { fixToUnknown: false, ignoreRestArgs: true } ], '@typescript-eslint/no-extra-non-null-assertion': 'error', '@typescript-eslint/no-for-in-array': 'error', '@typescript-eslint/no-inferrable-types': 'error', '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', '@typescript-eslint/no-var-requires': 'error', '@typescript-eslint/prefer-namespace-keyword': 'error'