# 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, "get" | "set" | "has" | "delete"> { /** * */ get(key: K): CodeGenValue | undefined; set(key: K, value: CodeGenValue): this; has(key: K): boolean; delete(key: K): boolean; } /** * @typedef {object} CodeGenMapOverloads * @property {(key: K) => CodeGenValue | undefined} get * @property {(key: K, value: CodeGenValue) => CodeGenerationResultData} set * @property {(key: K) => boolean} has * @property {(key: K) => boolean} delete */ /** * @typedef {Omit, "get" | "set" | "has" | "delete"> & CodeGenMapOverloads} CodeGenerationResultData */ ````