# require-template
Checks to see that `@template` tags are present for any detected type
parameters.
Currently checks `ClassDeclaration`, `FunctionDeclaration`, `TSDeclareFunction`,
`TSInterfaceDeclaration` or `TSTypeAliasDeclaration` such as:
```ts
export type Pairs = [D, V | undefined];
```
or
```js
/**
* @typedef {[D, V | undefined]} Pairs
*/
```
Note that in the latter TypeScript-flavor JavaScript example, there is no way
for us to firmly distinguish between `D` and `V` as type parameters or as some
other identifiers, so we use an algorithm that assumes that any single capital
letters are templates.
## Options
A single options object has the following properties.
### exemptedBy
Array of tags (e.g., `['type']`) whose presence on the document
block avoids the need for a `@template`. Defaults to an array with
`inheritdoc`. If you set this array, it will overwrite the default,
so be sure to add back `inheritdoc` if you wish its presence to cause
exemption of the rule.
### requireSeparateTemplates
Requires that each template have its own separate line, i.e., preventing
templates of this format:
```js
/**
* @template T, U, V
*/
```
Defaults to `false`.
|||
|---|---|
|Context|everywhere|
|Tags|`template`|
|Recommended|false|
|Settings||
|Options|`exemptedBy`, `requireSeparateTemplates`|
## Failing examples
The following patterns are considered problems:
````ts
/**
*
*/
type Pairs = [D, V | undefined];
// Message: Missing @template D
/**
*
*/
export type Pairs = [D, V | undefined];
// Message: Missing @template D
/**
* @typedef {[D, V | undefined]} Pairs
*/
// Message: Missing @template D
/**
* @typedef {[D, V | undefined]} Pairs
*/
// Settings: {"jsdoc":{"mode":"permissive"}}
// Message: Missing @template D
/**
* @template D, U
*/
export type Extras = [D, U, V | undefined];
// Message: Missing @template V
/**
* @template D, U
* @typedef {[D, U, V | undefined]} Extras
*/
// Message: Missing @template V
/**
* @template D, V
*/
export type Pairs = [D, V | undefined];
// "jsdoc/require-template": ["error"|"warn", {"requireSeparateTemplates":true}]
// Message: Missing separate @template for V
/**
* @template D, V
* @typedef {[D, V | undefined]} Pairs
*/
// "jsdoc/require-template": ["error"|"warn", {"requireSeparateTemplates":true}]
// Message: Missing separate @template for V
/**
* @template X
* @typedef {object} Pairs
* @property {D} foo
* @property {X} bar
*/
// Message: Missing @template D
/**
*
*/
interface GenericIdentityFn {
(arg: Type): Type;
}
// Message: Missing @template Type
/**
*
*/
export interface GenericIdentityFn {
(arg: Type): Type;
}
// Message: Missing @template Type
/**
*
*/
export default interface GenericIdentityFn {
(arg: Type): Type;
}
// Message: Missing @template Type
/**
*
*/
function identity(arg: Type): Type {
return arg;
}
// Message: Missing @template Type
/**
*
*/
export function identity(arg: Type): Type {
return arg;
}
// Message: Missing @template Type
/**
*
*/
export default function identity(arg: Type): Type {
return arg;
}
// Message: Missing @template Type
/**
*
*/
class GenericNumber {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
// Message: Missing @template NumType
/**
*
*/
export class GenericNumber {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
// Message: Missing @template NumType
/**
*
*/
export default class GenericNumber {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
// Message: Missing @template NumType
/**
*
*/
export default class {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
// Message: Missing @template NumType
/**
* @callback
* @param {[D, V | undefined]} someParam
*/
// Message: Missing @template D
/**
* @callback
* @returns {[D, V | undefined]}
*/
// Message: Missing @template D
/**
* @param bar
* @param baz
* @returns
*/
function foo(bar: T, baz: number): T;
function foo(bar: T, baz: boolean): T;
function foo(bar: T, baz: number | boolean): T {
return bar;
}
// Message: Missing @template T
/**
* @template
*/
// Settings: {"jsdoc":{"tagNamePreference":{"template":false}}}
// Message: Unexpected tag `@template`
````
## Passing examples
The following patterns are not considered problems:
````ts
/**
* @template D
* @template V
*/
export type Pairs = [D, V | undefined];
/**
* @template D
* @template V
* @typedef {[D, V | undefined]} Pairs
*/
/**
* @template D, U, V
*/
export type Extras = [D, U, V | undefined];
/**
* @template D, U, V
* @typedef {[D, U, V | undefined]} Extras
*/
/**
* @typedef {[D, U, V | undefined]} Extras
* @typedef {[D, U, V | undefined]} Extras
*/
/**
* @typedef Foo
* @prop {string} bar
*/
/**
* @template D
* @template V
* @typedef {object} Pairs
* @property {D} foo
* @property {V} bar
*/
/**
* @template Type
*/
interface GenericIdentityFn {
(arg: Type): Type;
}
/**
* @template Type
*/
export interface GenericIdentityFn {
(arg: Type): Type;
}
/**
* @template Type
*/
export default interface GenericIdentityFn {
(arg: Type): Type;
}
/**
* @template Type
*/
function identity(arg: Type): Type {
return arg;
}
/**
* @template Type
*/
export function identity(arg: Type): Type {
return arg;
}
/**
* @template Type
*/
export default function identity(arg: Type): Type {
return arg;
}
/**
* @template NumType
*/
class GenericNumber {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
/**
* @template NumType
*/
export class GenericNumber {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
/**
* @template NumType
*/
export default class GenericNumber {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
/**
* @template NumType
*/
export default class {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
/**
* @callback
* @template D
* @template V
* @param {[D, V | undefined]} someParam
*/
/**
* @callback
* @template D
* @template V
* @returns {[D, V | undefined]}
*/
/**
* @callback
* @returns {[Something | undefined]}
*/
/**
* @template {string | Buffer} [T=string, U=number]
* @typedef {object} Dirent
* @property {T} name name
* @property {U} aNumber number
* @property {string} parentPath path
*/
/**
* @type {Something}
*/
type Pairs = [D, V | undefined];
// "jsdoc/require-template": ["error"|"warn", {"exemptedBy":["type"]}]
/**
* @inheritdoc
* @typedef {[D, V | undefined]} Pairs
*/
// "jsdoc/require-template": ["error"|"warn", {"exemptedBy":["inheritdoc"]}]
/**
* Test interface for type definitions.
*
* @typeParam Foo - dummy type param
*/
export interface Test {
/**
*
*/
bar: Foo;
}
// Settings: {"jsdoc":{"tagNamePreference":{"template":"typeParam"}}}
/**
* @template T
* @typedef {T extends Record> ? F : never} ExtractFunction
*/
/**
*
*/
export interface CodeGenerationResultData extends Omit