A. L
A. L

Reputation: 12669

Function in javascript file can't detect its own type with declaration file

Is it possible for a file that has a corresponding declaration file to detect its own type in vscode?

Other files can get the typings, but not the file itself.

note the any

enter image description here

but this has proper typing

enter image description here

Reproduction

  1. Create a folder
  2. Run npm init
  3. Hit enter through everything
  4. Create 3 files index.js index.d.ts import.js

index.js

async function test(input) {
    return null
}

index.d.ts

type input_type = {
    name: string,
    salary: number
}

export function test(input : input_type) : Promise<null>

import.js

import * as t from './index'

t.test()

When you mouse over the test function in index.js it doesn't know its parameter type. But in import.js it knows it.

How can I get the index.js test function to know its own type.

Upvotes: 14

Views: 449

Answers (2)

Andrei Chernikov
Andrei Chernikov

Reputation: 350

The answer by TUTAMKHAMON should work without import if you want to just see the type name on hover. You won't be able to CTRL+click to go to the type in the declaration file, though. In this case, you should specify something like this:

/**
 * @typedef {{anything:any}} input_type
 * @param {input_type} input 
 */
async function test(input) {
    return null
}

enter image description here

There are several ways if you want to see the actual contents of the object and not just type name. You can provide a complete object breakdown inside the curly brackets:

/**
 * @param {{name:string,salary:number}} input 
 */
async function test(input) {
    return null
}

You can see object details on hover

It has a disadvantage though, you would need to specify this structure in multiple places.

An alternative way of doing this:

/**
 * @param {object} input 
 * @param {string} input.name
 * @param {number} input.salary
 */
async function test(input) {
    return null
}

enter image description here

You can also make use of the parameters destructuring feature:

/**
 * @param {object} input 
 * @param {string} input.name
 * @param {number} input.salary
 */
async function test({ name, salary }) {
    return null
}

enter image description here

If this is a normal javascript type, you can just specify it directly inside the curly brackets:

enter image description here

You might be wondering what this weird syntax is. This is jsdoc syntax, this is not typescript, although it has some overlap in syntax. You can learn more about jsdoc here: https://jsdoc.app/about-getting-started.html

EDIT

You can also specify return types like this:

/**
 * @param {object} input 
 * @param {string} input.name
 * @param {number} input.salary
 * @returns {Promise<string>}
 */
async function test(input) {
    return `The salary of ${input.name} is ${input.salary}`
}

async function foo() {
    const bar = await test({ name: "A", salary: 1000 })
}

enter image description here

Upvotes: 3

TUTAMKHAMON
TUTAMKHAMON

Reputation: 620

From what I understand, VSCode won't be able to infer the type since that type doesn't exist in the scope of index.js. However, it is imported into import.js.

The only workaround I can think of would be to help VSCode infer the type by using JSDoc, and even then we have to import the type:

/**
 * @typedef {import(".").input_type} input_type
 * @param {input_type} input 
 */
async function test(input) {
    return null
}

Shown working:

Solution shown working

Upvotes: 9

Related Questions