src/content/docs/linter/rules/use-explicit-type.mdx
import { Tabs, TabItem } from '@astrojs/starlight/components';
<Tabs> <TabItem label="TypeScript and TSX" icon="seti:typescript"> :::caution This rule is part of the [nursery](/linter/#nursery) group. This means that it is experimental and the behavior can change at any time. ::: ## Summary - Rule available since: `v1.9.3` - Diagnostic Category: [`lint/nursery/useExplicitType`](/reference/diagnostics#diagnostic-category) - This rule doesn't have a fix. - The default severity of this rule is [**error**](/reference/diagnostics#error). - Sources: - Inspired from [`@typescript-eslint/explicit-function-return-type`](https://typescript-eslint.io/rules/explicit-function-return-type) - Inspired from [`@typescript-eslint/explicit-module-boundary-types`](https://typescript-eslint.io/rules/explicit-module-boundary-types){
"linter": {
"rules": {
"nursery": {
"useExplicitType": "error"
}
}
}
}
Enforce types in functions, methods, variables, and parameters.
Functions in TypeScript often don't need to be given an explicit return type annotation. Leaving off the return type is less code to read or write and allows the compiler to infer it from the contents of the function.
However, explicit return types do make it visually clearer what type is returned by a function. They can also speed up TypeScript type-checking performance in large codebases with many large functions. Explicit return types also reduce the chance of bugs by asserting the return type, and it avoids surprising "action at a distance," where changing the body of one function may cause failures inside another function.
Annotating module-level variables serves a similar purpose. This rule only allows assignment of literals and some objects to untyped variables.
Objects that are allowed must not contain spread syntax and values that aren't literals.
Additionally, let and var variables with null or undefined as value require explicit annotation.
This rule enforces that functions do have an explicit return type annotation.
// Should indicate that no value is returned (void)
function test() {
return;
}
// Should indicate that a number is returned
var fn = function () {
return 1;
};
// Should indicate that a string is returned
var arrowFn = () => 'test';
class Test {
// Should indicate that no value is returned (void)
method() {
return;
}
}
// Should indicate that no value is returned (void)
function test(a: number) {
a += 1;
}
// Should use const assertions
var func = (value: number) => ({ type: 'X', value }) as any;
// Unspecified variable type
function fn(): string {
return "Not inline";
}
const direct = fn();
// Unspecified object member type
function fn(): string {
return "Not inline";
}
const nested = { result: fn() };
// let bindings of null and undefined are usually overwritten by other code
let foo = null;
The following example is considered incorrect for a higher-order function, as the returned function does not specify a return type:
var arrowFn = () => () => {};
var arrowFn = () => {
return () => { };
}
The following example is considered incorrect for a higher-order function because the function body contains multiple statements. We only check whether the first statement is a function return.
// A function has multiple statements in the body
function f() {
if (x) {
return 0;
}
return (): void => {}
}
// A function has multiple statements in the body
function f() {
let str = "test";
return (): string => {
str;
}
}
// A function has multiple statements in the body
function f() {
let str = "test";
}
The following example is considered incorrect for an interface method without a return type:
interface Array<Type> {
method();
}
The following example is considered incorrect for a type declaration of a function without a return type:
type MyObject = {
(input: string);
propertyName: string;
};
The following example is considered incorrect for an abstract class method without a return type:
abstract class MyClass {
public abstract method();
}
The following example is considered incorrect for an abstract class getter without a return type:
abstract class P<T> {
abstract get poke();
}
The following example is considered incorrect for a function declaration in a namespace without a return type:
declare namespace myLib {
function makeGreeting(s: string);
}
The following example is considered incorrect for a module function export without a return type:
declare module "foo" {
export default function bar();
}
The following example is considered incorrect because arg has any type.
var arrowFn = (arg: any): string => `test ${arg}`;
// No return value should be expected (void)
function test(): void {
return;
}
// A return value of type number
var fn = function (): number {
return 1;
}
// A return value of type string
var arrowFn = (): string => 'test';
// A literal value
const PREFIX = "/prefix";
// Explicit variable annotation
function func(): string {
return "";
}
let something: string = func();
class Test {
// No return value should be expected (void)
method(): void {
return;
}
}
The following example is considered correct code for a function immediately returning a value with as const:
var func = (value: number) => ({ foo: 'bar', value }) as const;
The following example is considered correct code for a value assigned using type assertion:
function fn(): string {
return "Not inline";
}
const direct = fn() as string;
const nested = { result: fn() as string };
The following examples are considered correct code for a function allowed within specific expression contexts, such as an IIFE, a function passed as an argument, or a function inside an array:
// Callbacks without return types
setTimeout(function() { console.log("Hello!"); }, 1000);
// Callbacks without argument types (immediately nested in a function call)
new Promise((resolve) => resolve(1));
// IIFE
(() => {})();
The following example is considered correct code for a higher-order function, where the returned function explicitly specifies a return type and the function body contains only one statement:
// the outer function returns an inner function that has a `void` return type
var arrowFn = () => (): void => {};
// the outer function returns an inner function that has a `void` return type
var arrowFn = () => {
return (): void => { };
}
The following examples are considered correct for type annotations on variables in function expressions:
// A function with a type assertion using `as`
var asTyped = (() => '') as () => string;
// A function with a type assertion using `<>`
var castTyped = <() => string>(() => '');
// A variable declarator with a type annotation.
type FuncType = () => string;
var arrowFn: FuncType = () => 'test';
// A function is a default parameter with a type annotation
type CallBack = () => void;
var f = (gotcha: CallBack = () => { }): void => { };
// A class property with a type annotation
type MethodType = () => void;
class App {
private method: MethodType = () => { };
}