Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 663
A. L Avatar asked Apr 19 '21 02:04

A. L


People also ask

Could not find a declaration file for module JavaScript?

If you are getting the "Could not find a declaration file for module 'X'" error when trying to import JavaScript files into your TypeScript files, you have to set the allowJs option to true in your tsconfig. json file.

How do I fix ts7016 error?

You can fix the error by writing typings yourself, or preferably by installing the types (if they do exist) using npm install --save-dev @types/react-native-material-color .

How do I include a file in a JavaScript file?

To include an external JavaScript file, we can use the script tag with the attribute src . You've already used the src attribute when using images. The value for the src attribute should be the path to your JavaScript file.

What is type D TS?

*. d. ts is the type definition files that allow to use existing JavaScript code in TypeScript. For example, we have a simple JavaScript function that calculates the sum of two numbers: // math.js.


2 Answers

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

like image 197
TUTAMKHAMON Avatar answered Oct 05 '22 02:10

TUTAMKHAMON


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

like image 30
Andrei Chernikov Avatar answered Oct 05 '22 00:10

Andrei Chernikov