Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions packages/eslint-plugin/docs/rules/require-explicit-array-types.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
description: 'Require explicit type annotations for empty arrays assigned to variables.'
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/require-explicit-array-types** for documentation.

This rule requires explicit type annotations for empty arrays assigned to variables. When assigning an empty array to a variable, TypeScript cannot infer the element type. The inferred type depends on your TypeScript configuration:

- **With `noImplicitAny: false`** (default): Empty arrays are inferred as `any[]`, which allows any type to be pushed but loses type safety.
- **With `noImplicitAny: true`** (strict mode): Empty arrays are inferred as `never[]`, which prevents adding any elements and causes type errors. However, TypeScript still allows `const arr = []` without a type annotation; errors only appear when you try to use the array.

This rule requires explicit type annotations for empty arrays at declaration time to ensure type safety. If you intentionally want `never[]`, explicitly type it: `const arr: never[] = []`.

## Examples

<Tabs>
<TabItem value="❌ Incorrect">

```ts
const arr = [];
const items = [];
let data = [];
var list = [];
```

</TabItem>
<TabItem value="✅ Correct">

```ts
const arr: string[] = [];
const items: number[] = [];
let data: boolean[] = [];
var list: any[] = [];

// If you intentionally want never[], you can be explicit about it
// Placeholder that will be replaced later
const placeholder: never[] = [];

// Non-empty arrays don't require explicit types
const numbers = [1, 2, 3];
const strings = ['a', 'b'];

// Type assertions are also acceptable
const typedArr = [] as string[];
const typedItems = [] as number[];
```

</TabItem>
</Tabs>

## When Not To Use It

If you prefer to rely on TypeScript's type inference for empty arrays, or if you consistently use type assertions instead of type annotations, you can turn this rule off.
1 change: 1 addition & 0 deletions packages/eslint-plugin/src/configs/eslintrc/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ export = {
'@typescript-eslint/require-array-sort-compare': 'error',
'require-await': 'off',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/require-explicit-array-types': 'error',
'@typescript-eslint/restrict-plus-operands': 'error',
'@typescript-eslint/restrict-template-expressions': 'error',
'no-return-await': 'off',
Expand Down
1 change: 1 addition & 0 deletions packages/eslint-plugin/src/configs/flat/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export default (
'@typescript-eslint/require-array-sort-compare': 'error',
'require-await': 'off',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/require-explicit-array-types': 'error',
'@typescript-eslint/restrict-plus-operands': 'error',
'@typescript-eslint/restrict-template-expressions': 'error',
'no-return-await': 'off',
Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin/src/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ import preferTsExpectError from './prefer-ts-expect-error';
import promiseFunctionAsync from './promise-function-async';
import relatedGetterSetterPairs from './related-getter-setter-pairs';
import requireArraySortCompare from './require-array-sort-compare';
import requireExplicitArrayTypes from './require-explicit-array-types';
import requireAwait from './require-await';
import restrictPlusOperands from './restrict-plus-operands';
import restrictTemplateExpressions from './restrict-template-expressions';
Expand Down Expand Up @@ -255,6 +256,7 @@ const rules = {
'promise-function-async': promiseFunctionAsync,
'related-getter-setter-pairs': relatedGetterSetterPairs,
'require-array-sort-compare': requireArraySortCompare,
'require-explicit-array-types': requireExplicitArrayTypes,
'require-await': requireAwait,
'restrict-plus-operands': restrictPlusOperands,
'restrict-template-expressions': restrictTemplateExpressions,
Expand Down
55 changes: 55 additions & 0 deletions packages/eslint-plugin/src/rules/require-explicit-array-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { AST_NODE_TYPES } from '@typescript-eslint/utils';

import { createRule } from '../util';

export type Options = [];
export type MessageIds = 'missingTypeAnnotation';

export default createRule<Options, MessageIds>({
name: 'require-explicit-array-types',
meta: {
type: 'problem',
docs: {
description:
'Require explicit type annotations for empty arrays assigned to variables',
},
messages: {
missingTypeAnnotation:
'Empty array assigned to variable must have an explicit type annotation. Use `{{kind}} {{name}}: Type[] = []` instead.',
},
schema: [],
},
defaultOptions: [],
create(context) {
return {
VariableDeclarator(node) {
const id = node.id;
if (id.type !== AST_NODE_TYPES.Identifier) {
return;
}

if (
node.init &&
node.init.type === AST_NODE_TYPES.ArrayExpression &&
node.init.elements.length === 0 &&
!id.typeAnnotation
) {
const parent = node.parent;
const kind =
parent.type === AST_NODE_TYPES.VariableDeclaration
? parent.kind
: 'const';

context.report({
node,
messageId: 'missingTypeAnnotation',
data: {
name: id.name,
kind,
},
});
}
},
};
},
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { RuleTester } from '@typescript-eslint/rule-tester';

import rule from '../../src/rules/require-explicit-array-types';

const ruleTester = new RuleTester();

ruleTester.run('require-explicit-array-types', rule, {
valid: [
// With type annotations
'const arr: string[] = [];',
'const arr: number[] = [];',
'const arr: boolean[] = [];',
'const arr: any[] = [];',
'const arr: unknown[] = [];',
'const arr: Array<string> = [];',
'const arr: Array<number> = [];',
'const arr: (string | number)[] = [];',
'let arr: string[] = [];',
'var arr: string[] = [];',

// Non-empty arrays (should not trigger)
'const arr = [1, 2, 3];',
'const arr = ["a", "b"];',

// Arrays with type annotation and elements
'const arr: number[] = [1, 2, 3];',
'const arr: string[] = ["a", "b"];',

// Non-array assignments
'const x = 5;',
'const y = "hello";',
'const z = null;',
'const w = undefined;',

// Array with type assertion
'const arr = [] as string[];',
'const arr = [] as number[];',

// Explicit never[] type (intentional placeholder)
'const placeholder: never[] = [];',
],
invalid: [
{
code: 'const arr = [];',
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'arr',
kind: 'const',
},
},
],
},
{
code: 'let arr = [];',
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'arr',
kind: 'let',
},
},
],
},
{
code: 'var arr = [];',
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'arr',
kind: 'var',
},
},
],
},
{
code: `
const items = [];
const data = [];
`,
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'items',
kind: 'const',
},
},
{
messageId: 'missingTypeAnnotation',
data: {
name: 'data',
kind: 'const',
},
},
],
},
{
code: `
const arr = [];
arr.push(1);
`,
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'arr',
kind: 'const',
},
},
],
},
{
code: `
function test() {
const local = [];
}
`,
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'local',
kind: 'const',
},
},
],
},
{
code: `
if (true) {
const arr = [];
}
`,
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'arr',
kind: 'const',
},
},
],
},
{
code: `
for (let i = 0; i < 10; i++) {
const items = [];
}
`,
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'items',
kind: 'const',
},
},
],
},
{
code: `
const a = [];
const b: number[] = [];
const c = [];
`,
errors: [
{
messageId: 'missingTypeAnnotation',
data: {
name: 'a',
kind: 'const',
},
},
{
messageId: 'missingTypeAnnotation',
data: {
name: 'c',
kind: 'const',
},
},
],
},
],
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading