TypeScript 的 JSDoc 通用 typedef

Tom*_*uer 8 javascript jsdoc typescript

我在 JavaScript 项目中使用 JSDoc,该项目使用 TypeScript 编译器进行检查。

在 TypeScript 中,我可以创建一个泛型类型,如下所示:

type Optional<TType extends string> = { type: TType; optional?: boolean; } | { type: `${TType}?` };
type OptionalThing = Optional<'thing'>;
Run Code Online (Sandbox Code Playgroud)

的解析和扁平化值OptionalThing现在是这样的:

type OptionalThing = 
  | { type: 'thing'; optional?: boolean; }
  | { type: 'thing?'; }
Run Code Online (Sandbox Code Playgroud)

此类型创建一个类型联合,其中一个成员类型具有thing该字段的文字和 const 值type ,并且有一个附加的optional布尔字段,而另一种成员类型具有该字段thing?的文字和 consttype值,但没有该optional字段。

后缀?ontype是一种简写语法,用于在我正在解决的问题中将某个事物标记为可选,因此optional需要禁止另外指定,否则可能会表示无效值:{ type: 'thing?', optional: false }

换句话说:

/* These are allowed - they conform to the type */
const optionalThing1: OptionalThing = { type: 'thing?' };
const optionalThing2: OptionalThing = { type: 'thing', optional: true };
const optionalThing3: OptionalThing = { type: 'thing', optional: false };

// This is disallowed, `optional` cannot be specified while `type` has `?` suffix
const optionalThing4: OptionalThing = { type: 'thing?', optional: false };

// This is disallowed, `type` must be either `thing` or `thing?` const string
const optionalThing5: OptionalThing = { type: 'not literally "thing"' };
Run Code Online (Sandbox Code Playgroud)

Playground(配置为 TypeScript)

我无法将其转换为在 TypeScript 中具有相同行为的 JSDoc。我试过这个:

/** @typedef {{ type: T; optional?: boolean; } | { type: `${T}?`; }} Type<T> */
/** @template {string} T */

/** @typedef {Type<'thing'>} ThingType */
// Error: Type 'Type' is not generic.
Run Code Online (Sandbox Code Playgroud)

Playground(配置为 JavaScript)

如何typedef在 JSDoc 中创建泛型,以便当 TypeScript 检查 JavaScript 和 JSDoc 版本时上述 TypeScript 逻辑以相同的方式工作?

Car*_*nas 10

您的代码几乎是正确的,您只需将@template@typedef标签放在同一个 JSDoc 注释中,如下所示:

/** 
 * @typedef {{ type: T; optional?: boolean; } | { type: `${T}?`; }} Type<T>
 * @template {string} T
 */

/**
 * @typedef {Type<'thing'>} ThingType
 */
Run Code Online (Sandbox Code Playgroud)

游乐场链接

一般来说,当您需要定义泛型类型时,您需要在同一个 JSDoc 注释中除了该@typedef标签之外还有一个标签。@template

但是,您不能将其放在ThingType typedef同一个 JSDoc 中,否则它也将成为泛型类型。