Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I hide 'private' methods with JSDoc Typescript Declarations?

Let's say I have a JavaScript class

/**
 * @element my-element
 */
export class MyElement extends HTMLElement {
  publicMethod() {}
  /** @private */
  privateMethod() {}
}

customElements.define('my-element', MyElement);

and a declaration file, generated using declaration and allowJs:

export class MyElement extends HTMLElement {
  publicMethod(): void;
  /** @private */
  privateMethod(): void
}

I also, in a post-build script, concat this to the declaration file:

declare global { interface HTMLElementTagNameMap { 'my-element': MyElement; } }

When using this element in a typescript file, I get access to privateMethod in autocomplete.

import 'my-element'
const me = document.createElement("my-element")
me.// autocompletes `privateMethod`

How can I instruct tsc to mark as private any methods, fields, or properties that are annotated with the @private JSDoc tag?

like image 834
Benny Powers Avatar asked Jan 27 '20 06:01

Benny Powers


People also ask

Can we use JSDoc type in typescript?

You can use most JSDoc type syntax and any TypeScript syntax, from the most basic like string to the most advanced, like conditional types. @type can specify a union type — for example, something can be either a string or a boolean.

How do you declare a type in typescript?

Declared in a TypeScript declaration, either global or imported. Declared in a JSDoc @typedef tag. You can use most JSDoc type syntax and any TypeScript syntax, from the most basic like string to the most advanced, like conditional types. @type can specify a union type — for example, something can be either a string or a boolean.

What is the correct syntax for private fields in typescript?

According to the JSDoc documentation, using /** @private */ is the correct syntax, but this is not how TypeScript handles it. You will need to leverage TypeScripts syntax to handle this, it will not work with JSDoc alone. TypeScript 3.8 and up supports ES6 style private fields.

How to import declarations from other files in typescript?

You can import declarations from other files using import types. This syntax is TypeScript-specific and differs from the JSDoc standard: import types can be used to get the type of a value from a module if you don’t know the type, or if it has a large type that is annoying to type:


2 Answers

According to the JSDoc documentation, using /** @private */ is the correct syntax, but this is not how TypeScript handles it. You will need to leverage TypeScripts syntax to handle this, it will not work with JSDoc alone.

TypeScript 3.8 and up supports ES6 style private fields. You can denote a private field using the # symbol at the beginning of your method as such:

class Animal {
  #name: string;
  constructor(theName: string) {
    this.#name = theName;
  }
}

// example

new Animal("Cat").#name;
Property '#name' is not accessible outside class 'Animal' because it has a private identifier.

Alternatively, TypeScript also allows you to declare a field as private using the private marker and will provide the desired result. Doing this will not show the privateMethod during autocompletion (at least for it me it does not).

/**
 * @element my-element
 */
class MyElement extends HTMLElement {
  publicMethod() {}
  /** @private */
  private privateMethod() {}
}

let element = new MyElement()

element.privateMethod()
// Error: Property 'privateMethod' is private and only accessible within class 'MyElement'.

Here is an example of this working with VS Code intellisense.

enter image description here

like image 116
Nitsew Avatar answered Oct 20 '22 14:10

Nitsew


Make sure you are using correct version of typescript. Typescript 3.8 added support for this, using Typescript 3.8 or heigher should support @private jsdoc modifier.

You can use tsc -h to get information about installed version of typescript compiler.

like image 2
Dipen Shah Avatar answered Oct 20 '22 12:10

Dipen Shah