ChatGPT解决这个技术问题 Extra ChatGPT

About "*.d.ts" in TypeScript

I am curious about .d.ts declaration files because I am new to the TypeScript programming language. I was told by someone that .d.ts files are are similar to .h header files in the C & C++ programming languages, however, the .d.ts files don't seem to work quite the same. Currently, I am failing to understand how to properly use the .d.ts files. It would appear that I cant add my .js or .ts files to the .d.ts files, so the only way my project will work is if it contains all three file types. That seems like a lot of files. To help me better understand how the .d.ts files are related to JavaScript & TypeScript, I have some questions I would like to ask.

What is the relationship between the three files? the relationship between them? How can I use the *.d.ts file? Does it mean I can delete the *.ts file permanently? If so, how can the *.d.ts file know which JS file is mapping to itself?

It would be very nice if someone can give me an example.

For future people: check out the TypeScript doc: typescriptlang.org/docs/handbook/declaration-files/templates/…

P
Parzh from Ukraine

The "d.ts" file is used to provide typescript type information about an API that's written in JavaScript. The idea is that you're using something like jQuery or underscore, an existing javascript library. You want to consume those from your typescript code.

Rather than rewriting jquery or underscore or whatever in typescript, you can instead write the d.ts file, which contains only the type annotations. Then from your typescript code you get the typescript benefits of static type checking while still using a pure JS library.

This works thanks to TypeScript's constraint of not letting you add the ".ts" extension at the end of the import statement. Because of that, when you reference some file, let's say, my-module.js, if there is a my-module.d.ts next to it, then TypeScript will include its content:

src/
  my-module.js
  my-module.d.ts
  index.ts

my-module.js

const thing = 42;

module.exports = { thing };

my-module.d.ts

export declare const thing: number;

index.ts

import { thing } from "./my-module"; // <- no extension

// runtime implementation of `thing` is taken from ".js"
console.log(thing); // 42

// type declaration of `thing` is taken from ".d.ts"
type TypeOfThing = typeof thing; // number

Many thanks! But how to map a *.d.ts file to a js file? How does the js file know which d.ts file is mapping to itself? Can you give me an example?
But the d.ts file is generated from the js file, and if the js file knows nothing about d.ts. How to call the functions from d.ts in other ts files without the js file? I'm puzzled......
See stackoverflow.com/questions/18091724/…. You need to add a ///<reference line to the top of the consuming ts file. You'll need to have both the d.ts and the .js file available.
the d.ts file is generally handwritten from js file documentation. A large number of these are available for popular javascript libraries : github.com/borisyankov/DefinitelyTyped
Where do you put custom d.ts files if you're making custom ones for your project?
i
iliketocode

d stands for Declaration Files:

When a TypeScript script gets compiled there is an option to generate a declaration file (with the extension .d.ts) that functions as an interface to the components in the compiled JavaScript. In the process the compiler strips away all function and method bodies and preserves only the signatures of the types that are exported. The resulting declaration file can then be used to describe the exported virtual TypeScript types of a JavaScript library or module when a third-party developer consumes it from TypeScript. The concept of declaration files is analogous to the concept of header file found in C/C++.

declare module arithmetics {
    add(left: number, right: number): number;
    subtract(left: number, right: number): number;
    multiply(left: number, right: number): number;
    divide(left: number, right: number): number;
}

Type declaration files can be written by hand for existing JavaScript libraries, as has been done for jQuery and Node.js. Large collections of declaration files for popular JavaScript libraries are hosted on GitHub in DefinitelyTyped and the Typings Registry. A command-line utility called typings is provided to help search and install declaration files from the repositories.


Note: the typings command line tool isn't really needed since TypeScript 2.0. The more up-to-date approach is to use typing wrappers via the npm repository under the @types namespace. For further detail see github.com/typings/typings/blob/master/README.md
@takeshin I've got a question. Do I need to generate .d.ts files of .tsx files which are used only inside of my project? Does those are adding something else besides of giving possibility 3rd party libraries additional info?
j
j D3V

I learned the following from having to painstakingly map a JavaScript project using .d.ts files.

Using a .d.ts file to map JavaScript requires that you name your .d.ts files the same as you name your .js files. Each .js file needs to be kept inline (kept in the same directory) with the .d.ts file that has the same name. Point the JS/TS code that needs the types from the .d.ts files to the .d.ts files.

eg: test.js and test.d.ts are in the testdir/ folder, then you import it like this in a react component:

import * as Test from "./testdir/test";

The .d.ts file was exported as a namespace like this:

export as namespace Test;
    
export interface TestInterface1{}
export class TestClass1{}

Nobody gave an answer as to how to connect d.ts to js, so i thought this is the right place.
Note that if you're creating a declaration file for some JS that you didn't create (a package from npm for example) that the .d.ts file must also be named the same as the package to be imported.
What if the module is impored like this (don't ask me why 🤬): import x from "x/x.js" i.e. has a file extension at the end? Tried naming the d.ts file x.js.d.ts but that doesn't seem to do the trick
file *.d.ts must be "the same name" and the "same folder" with *.js. I think the above answer is right
B
Boris Yakubchik

Worked example for a specific case:

Let's say you have my-module that you're sharing via npm.

You install it with npm install my-module

You use it thus:

import * as lol from 'my-module';

const a = lol('abc', 'def');

The module's logic is all in index.js:

module.exports = function(firstString, secondString) {

  // your code

  return result
}

To add typings, create a file index.d.ts:

declare module 'my-module' {
  export default function anyName(arg1: string, arg2: string): MyResponse;
}

interface MyResponse {
  something: number;
  anything: number;
}

M
Michal

Like @takeshin said .d stands for declaration file for typescript (.ts).

Few points to be clarified before proceeding to answer this post -

Typescript is syntactic superset of javascript. Typescript doesn't run on its own, it needs to be transpiled into javascript (typescript to javascript conversion) "Type definition" and "Type checking" are major add-on functionalities that typescript provides over javascript. (check difference between type script and javascript)

If you are thinking if typescript is just syntactic superset, what benefits does it offer - https://basarat.gitbooks.io/typescript/docs/why-typescript.html#the-typescript-type-system

To Answer this post -

As we discussed, typescript is superset of javascript and needs to be transpiled into javascript. So if a library or third party code is written in typescript, it eventually gets converted to javascript which can be used by javascript project but vice versa does not hold true.

For ex -

If you install javascript library -

npm install --save mylib

and try importing it in typescript code -

import * from "mylib";

you will get error.

"Cannot find module 'mylib'."

As mentioned by @Chris, many libraries like underscore, Jquery are already written in javascript. Rather than re-writing those libraries for typescript projects, an alternate solution was needed.

In order to do this, you can provide type declaration file in javascript library named as *.d.ts, like in above case mylib.d.ts. Declaration file only provides type declarations of functions and variables defined in respective javascript file.

Now when you try -

import * from "mylib";

mylib.d.ts gets imported which acts as an interface between javascript library code and typescript project.


Where exactly do you put mylib.d.ts? Can it be anywhere in your code base? Only at the top level? Does some config file need to point to it?
J
James

This answer assumes you have some JavaScript that you don't want to convert to TypeScript, but you want to benefit from type checking with minimal changes to your .js. A .d.ts file is very much like a C or C++ header file. Its purpose is to define an interface. Here is an example:

mashString.d.ts

/** Makes a string harder to read. */
declare function mashString(
    /** The string to obscure */
    str: string
):string;
export = mashString;

mashString.js

// @ts-check
/** @type {import("./mashString")} */
module.exports = (str) => [...str].reverse().join("");

main.js

// @ts-check
const mashString = require("./mashString");
console.log(mashString("12345"));

The relationship here is: mashString.d.ts defines an interface, mashString.js implements the interface and main.js uses the interface.

To get the type checking to work you add // @ts-check to your .js files. But this only checks that main.js uses the interface correctly. To also ensure that mashString.js implements it correctly we add /** @type {import("./mashString")} */ before the export.

You can create your initial .d.ts files using tsc -allowJs main.js -d then edit them as required manually to improve the type checking and documentation.

In most cases the implementation and interface have the same name, here mashString. But you can have alternative implementations. For example we could rename mashString.js to reverse.js and have an alternative encryptString.js.


K
Kostas Minaidis

I guess I could add my 2 cents here

// somefile.d.ts
export type SomeItem = {
  weight: number
}

export type ItemStorage = {
  name: string
  items: SomeItem[]
}
// somefile.js
// @ts-check
/** @typedef { import('./somefile.d.ts').SomeItem } SomeItem */
/** @typedef { import('./somefile.d.ts').ItemStorage } ItemStorage */

/**
 * @param { StorageItem } item
 */
function doSomething(item) {
  item. // intellisense
  // your code here
}

The neat thing about this is that one can gradually incorporate types in an existing javascript project.


C
Chan Chung

For example, you got the problem to use 'alertifyjs' module from npm.

Create 'anyNameYoulike.d.ts' (ex. you made this file in src folder) In the file declare module 'alertifyjs'; enter image description here in tsconfig.json Under "compilerOptions" "typeRoots": ["node_modules/@types", "src/anyNameYoulike.d.ts"]


Please repost this as a comment.
@Yserbius How could the length of this answer be a comment?