typedef
Require type annotations in certain places.
TypeScript cannot always infer types for all places in code. Some locations require type annotations for their types to be inferred.
This rule can enforce type annotations in locations regardless of whether they're required. This is typically used to maintain consistency for element types that sometimes require them.
class ContainsText {
// There must be a type annotation here to infer the type
delayedText: string;
// `typedef` requires a type annotation here to maintain consistency
immediateTextExplicit: string = 'text';
// This is still a string type because of its initial value
immediateTextImplicit = 'text';
}
To enforce type definitions existing on call signatures, use
explicit-function-return-type
, orexplicit-module-boundary-types
.
Requiring type annotations unnecessarily can be cumbersome to maintain and generally reduces code readability. TypeScript is often better at inferring types than easily written type annotations would allow.
Instead of enabling typedef
, it is generally recommended to use the --noImplicitAny
and --strictPropertyInitialization
compiler options to enforce type annotations only when useful.
module.exports = {
"rules": {
"@typescript-eslint/typedef": "error"
}
};
Try this rule in the playground ↗
Options
This rule accepts the following options:
type Options = [
{
arrayDestructuring?: boolean;
arrowParameter?: boolean;
memberVariableDeclaration?: boolean;
objectDestructuring?: boolean;
parameter?: boolean;
propertyDeclaration?: boolean;
variableDeclaration?: boolean;
variableDeclarationIgnoreFunction?: boolean;
},
];
const defaultOptions: Options = [
{
arrayDestructuring: false,
arrowParameter: false,
memberVariableDeclaration: false,
objectDestructuring: false,
parameter: false,
propertyDeclaration: false,
variableDeclaration: false,
variableDeclarationIgnoreFunction: false,
},
];
For example, with the following configuration:
{
"rules": {
"@typescript-eslint/typedef": [
"error",
{
"arrowParameter": true,
"variableDeclaration": true
}
]
}
}
- Type annotations on arrow function parameters are required
- Type annotations on variables are required
arrayDestructuring
Whether to enforce type annotations on variables declared using array destructuring.
Examples of code with { "arrayDestructuring": true }
:
- ❌ Incorrect
- ✅ Correct
const [a] = [1];
const [b, c] = [1, 2];
Open in Playgroundconst [a]: number[] = [1];
const [b]: [number] = [2];
const [c, d]: [boolean, string] = [true, 'text'];
for (const [key, val] of new Map([['key', 1]])) {
}
Open in PlaygroundarrowParameter
Whether to enforce type annotations for parameters of arrow functions.
Examples of code with { "arrowParameter": true }
:
- ❌ Incorrect
- ✅ Correct
const logsSize = size => console.log(size);
['hello', 'world'].map(text => text.length);
const mapper = {
map: text => text + '...',
};
Open in Playgroundconst logsSize = (size: number) => console.log(size);
['hello', 'world'].map((text: string) => text.length);
const mapper = {
map: (text: string) => text + '...',
};
Open in PlaygroundmemberVariableDeclaration
Whether to enforce type annotations on member variables of classes.
Examples of code with { "memberVariableDeclaration": true }
:
- ❌ Incorrect
- ✅ Correct
class ContainsText {
delayedText;
immediateTextImplicit = 'text';
}
Open in Playgroundclass ContainsText {
delayedText: string;
immediateTextImplicit: string = 'text';
}
Open in PlaygroundobjectDestructuring
Whether to enforce type annotations on variables declared using object destructuring.
Examples of code with { "objectDestructuring": true }
:
- ❌ Incorrect
- ✅ Correct
const { length } = 'text';
const [b, c] = Math.random() ? [1, 2] : [3, 4];
Open in Playgroundconst { length }: { length: number } = 'text';
const [b, c]: [number, number] = Math.random() ? [1, 2] : [3, 4];
for (const { key, val } of [{ key: 'key', val: 1 }]) {
}
Open in Playgroundparameter
Whether to enforce type annotations for parameters of functions and methods.
Examples of code with { "parameter": true }
:
- ❌ Incorrect
- ✅ Correct
function logsSize(size): void {
console.log(size);
}
const doublesSize = function (size): number {
return size * 2;
};
const divider = {
curriesSize(size): number {
return size;
},
dividesSize: function (size): number {
return size / 2;
},
};
class Logger {
log(text): boolean {
console.log('>', text);
return true;
}
}
Open in Playgroundfunction logsSize(size: number): void {
console.log(size);
}
const doublesSize = function (size: number): number {
return size * 2;
};
const divider = {
curriesSize(size: number): number {
return size;
},
dividesSize: function (size: number): number {
return size / 2;
},
};
class Logger {
log(text: boolean): boolean {
console.log('>', text);
return true;
}
}
Open in PlaygroundpropertyDeclaration
Whether to enforce type annotations for properties of interfaces and types.
Examples of code with { "propertyDeclaration": true }
:
- ❌ Incorrect
- ✅ Correct
type Members = {
member;
otherMember;
};
Open in Playgroundtype Members = {
member: boolean;
otherMember: string;
};
Open in PlaygroundvariableDeclaration
Whether to enforce type annotations for variable declarations, excluding array and object destructuring.
Examples of code with { "variableDeclaration": true }
:
- ❌ Incorrect
- ✅ Correct
const text = 'text';
let initialText = 'text';
let delayedText;
Open in Playgroundconst text: string = 'text';
let initialText: string = 'text';
let delayedText: string;
Open in PlaygroundvariableDeclarationIgnoreFunction
Ignore variable declarations for non-arrow and arrow functions.
Examples of code with { "variableDeclaration": true, "variableDeclarationIgnoreFunction": true }
:
- ❌ Incorrect
- ✅ Correct
const text = 'text';
Open in Playgroundconst a = (): void => {};
const b = function (): void {};
const c: () => void = (): void => {};
class Foo {
a = (): void => {};
b = function (): void {};
c: () => void = (): void => {};
}
Open in PlaygroundWhen Not To Use It
If you are using stricter TypeScript compiler options, particularly --noImplicitAny
and/or --strictPropertyInitialization
, you likely don't need this rule.
In general, if you do not consider the cost of writing unnecessary type annotations reasonable, then do not use this rule.