Что за файлы d ts
The purpose of this guide is to teach you how to write a high-quality definition file. This guide is structured by showing documentation for some API, along with sample usage of that API, and explaining how to write the corresponding declaration.
These examples are ordered in approximately increasing order of complexity.
Objects with Properties
The global variable myLib has a function makeGreeting for creating greetings, and a property numberOfGreetings indicating the number of greetings made so far.
Use declare namespace to describe types or values accessed by dotted notation.
The getWidget function accepts a number and returns a Widget, or accepts a string and returns a Widget array.
Reusable Types (Interfaces)
Use an interface to define a type with properties.
Reusable Types (Type Aliases)
Anywhere a greeting is expected, you can provide a string , a function returning a string , or a Greeter instance.
You can use a type alias to make a shorthand for a type:
The greeter object can log to a file or display an alert. You can provide LogOptions to .log(. ) and alert options to .alert(. )
Use namespaces to organize types.
You can also create nested namespaces in one declaration:
You can create a greeter by instantiating the Greeter object, or create a customized greeter by extending from it.
Use declare class to describe a class or class-like object. Classes can have properties and methods as well as a constructor.
The global variable foo contains the number of widgets present.
Use declare var to declare variables. If the variable is read-only, you can use declare const . You can also use declare let if the variable is block-scoped.
You can call the function greet with a string to show a greeting to the user.
Use declare function to declare functions.
Introduction
How to write a high-quality TypeScript Declaration (d.ts) file
Library Structures
How to structure your d.ts files
The TypeScript docs are an open source project. Help us improve these pages by sending a Pull Request ❤
Для установки связи с внешними файлами скриптов javascript в TS служат декларативные или заголовочные файлы. Это файлы с расширением .d.ts , они описывают синтаксис и структуру функций и свойств, которые могут использоваться в программе, не предоставляя при этом конкретной реализации. Их действие во многом похоже на работу файлов с расширением .h в языках C/C++. Они выполняют своего рода роль оберток над библиотеками JavaScript.
Рассмотрим, как мы можем использовать заголовочные файлы. Иногда в программах на javascript используются глобальные переменные, которые должны быть видны для всех функций приложения. Например, пусть на веб-странице (или во внешнем подключаемом файле javascript) в коде js определена переменная:
В данном случае для простоты переменная определена веб-странице, хотя она также могла быть определена во внешнем подключенном js-файле.
И, допустим, мы хотим использовать эту переменную message в коде TypeScript в файле app.ts:
При запуске приложения компилятор TS не сможет скомпилировать программу, так как для кода TS глобальная переменная пока не существует. В этом случае нам надо подключать определение глобальной переменной с помощью декларативных файлов. Для этого добавим в проект новый файл, который назовем globals.d.ts и который будет иметь следующее содержимое:
С помощью ключевого слова declare в программу на TS подключается определение глобальной переменной.
То есть у нас получится следующая структура проекта:
Компиляция
Если мы компилируем, передавая компилятору в консоли название файла:
То в этом случае компилятор не найдет автоматически файл globals.d.ts. В этом случае нам надо в файле app.ts явно указать расположение файла globals.d.ts с помощью директивы reference
Если же мы полагаемся на файл конфигурации tsconfig.json, просто выполняя команду
Подобным образом мы можем подлюкчать другие компоненты кода JavaScript - функции, объекты, классы. Рассмотрим их подключение.
Функции
Пусть на веб-странице в коде js объявлены две следующие функции:
Функция hello() выводит значение переменной message на консоль, а функция sum() возвращает сумму двух чисел.
И, допустим, в коде TS мы хотим вызывать эти функции:
В этом случае подключение в файле globals.d.ts выглядело бы так:
Подключение объектов
Пусть в коде JavaScript есть следующий объект:
Используем этот объект в коде typescript:
В этом случае определение объекта в файле globals.d.ts выглядело бы так:
Подключени сложных объектов
Однако может возникнуть сложность с подключением более сложных объектов. Например, пусть есть такой объект javascript:
Для данного массива объектов в файле globals.d.ts мы можем определить соответствующий отдельному объекту интерфейс и подключить массив объектов некоторого интерфейса, который содержит два свойства X и Y:
И в TS мы сможем использовать этот массив:
Консольный вывод браузера:
Точка с координатами X = 10 Y = 34 Точка с координатами X = 24 Y = 65 Точка с координатами X = 89 Y = 12
Подключение классов
Рассмотрим последний пример - подключение в typescript классов, определенных в javascript. Пусть в коде JavaScript определен следующий класс Person:
Для этого класса в файле globals.d.ts определим следующее объявление класса:
Для класса прописываем все его поля и методы, при этом методы (в том числе конструктор) не имеют реализации, для них только определяются параметры и их типы и тип возвращаемого значения.
*.d.ts файлы - это файлы декларации типов. Они содержат описание типов без реализации. Например, сигнатуры функций без тела, название и тип глобальных переменных без значений. В основном файлы декларации типов нужны для написания библиотек. Они нужны тогда, когда:
Если выложить этот код в качестве библиотеки (например, сделать и опубликовать npm-пакет), то этим кодом смогут пользоваться только проекты с настроенным TypeScript. Более того, возможно потребуется дополнительная настройка TypeScript, чтобы при компиляции проекта он компилировал и файлы нашей библиотеки.
Другой способ публикации библиотеки - скомпилировать TypeScript в JavaScript и выложить уже JavaScript файлы. В таком случаи этой библиотекой могут пользоваться любые проекты, как обычной библиотекой на JavaScript. Однако, если эту библиотеку планируется использовать в TypeScript проекте - хотелось бы сохранить типизацию. Здесь и появляются .d.ts файлы. Перед публикацией библиотеки мы компилируем TypeScript в JavaScript, но конфигурируем компилятор так, чтобы рядом с получившимися .js файлами, он создал .d.ts файлы по каждому файлу JavaScript-а. Далее мы публикуем и .js файлы и .d.ts файлы. Теперь, если использовать эту библиотеку в JavaScript проекте, то будут просто использоваться .js файлы, если использовать в TypeScript проекте, то при компиляции будут использоваться .d.ts, а runtime пред компилированные .js .
*.d.ts файлы можно получить автоматически или написать вручную. Для автоматической генерации нужно, чтобы библиотека изначально был на TypeScript и компилятор был настроен на генерацию файлов декларации. Например, для кода выше компилятор сгенерирует такие декларации:
Если библиотека изначально написана на JavaScript (или на другом языке, но не на TypeScript) или автоматическая генерация деклараций типов по TypeScript-файлам по каким-то причинам не устраивает, то файлы деклараций можно написать вручную. Возможно есть сторонние генераторы *.d.ts файлов по JavaScript, TypeScript и другим языкам, но их мы рассматривать не будем.
Одно из главных ключевых слов в файлах деклараций - это слово declare . Используя это слово в какой-либо синтаксической конструкции (например, в объявлении класса), мы указываем TypeScript-у, что ее нужно интерпретировать, как декларацию. Рассмотрим два блока кода выше. При описании класса в *.ts файле мы описывали всю сигнатуру класса, правила инициализации полей, тела конструктора и методов и модификаторы доступа. В файле декларации класс помечен словом declare и у него описан лишь публичный интерфейс взаимодействия с этим классом без реализации - что и с какими параметрами можно вызывать, что в итоге получится, а также к каким полям и методам есть доступ.
Рассмотрим автоматическую генерацию файлов декларации и то, как ее можно изменять. Если объявлены глобальные переменные
то в их декларациях используется declare и сохраняется способ объявления, но теряется значение - оно с точки зрения проверки на типы не важно:
Для переменной объявленной с использованием const автоматический вывод типов может вывести литеральный тип.
Для декларации функций нужно указать их сигнатуры - название, параметры и их типы и возвращаемое значение.
Если функция использует generic-и, то в декларации нужно указать и generic-параметры и их ограничения.
Для декларации классов нужно использовать особенности декларации переменных и функций. По их подобию сделана декларация полей, методов и конструктора. Ключевое слово declare используется только у самого класса. Поля декларируются со всеми модификаторами, но без инициализации. Методы также декларируются со всеми модификаторами и описанной сигнатурой, но без тела.
Первый способ - включить .d.ts ф айлы прямо в библиотеку с .js файлами. Это может быть сделано по разному: можно каждый .d.ts файл хранить рядом с каждым соответствующим .js файлом, а можно внести все .d.ts файлы в отдельную директорию или "сбандлить" в один файл. Преимущество такого подхода в том, что пользоваться этой библиотекой в TypeScript проекте можно "из коробки". Недостаток - .d.ts файлы добавляют размер библиотеке. Если проект не использует TypeScript, то .d.ts файлы ему не нужно. Но из-за того что они встроены в библиотеку, они всегда будут приходить вместе с ней.
Comparing JavaScript to an example DTS
Common CommonJS Patterns
A module using CommonJS patterns uses module.exports to describe the exported values. For example, here is a module which exports a function and a numerical constant:
This can be described by the following .d.ts :
The TypeScript playground can show you the .d.ts equivalent for JavaScript code. You can try it yourself here.
The .d.ts syntax intentionally looks like ES Modules syntax. ES Modules was ratified by TC39 in 2019, while it has been available via transpilers for a long time, however if you have a JavaScript codebase using ES Modules:
This would have the following .d.ts equivalent:
In CommonJS you can export any value as the default export, for example here is a regular expression module:
Which can be described by the following .d.ts:
One style of exporting in CommonJS is to export a function. Because a function is also an object, then extra fields can be added and are included in the export.
Which can be described with:
Note that using export default in your .d.ts files requires esModuleInterop: true to work. If you can’t have esModuleInterop: true in your project, such as when you’re submitting a PR to Definitely Typed, you’ll have to use the export= syntax instead. This older syntax is harder to use but works everywhere. Here’s how the above example would have to be written using export= :
See Module: Functions for details of how that works, and the Modules reference page.
Handling Many Consuming Import
There are many ways to import a module in modern consuming code:
Covering all of these cases requires the JavaScript code to actually support all of these patterns. To support many of these patterns, a CommonJS module would need to look something like:
Types in Modules
You may want to provide a type for JavaScript code which does not exist
This can be described with:
This example is a good case for using generics to provide richer type information:
Now the type of the array propagates into the ArrayMetadata type.
The types which are exported can then be re-used by consumers of the modules using either import or import type in TypeScript code or JSDoc imports.
Namespaces in Module Code
Trying to describe the runtime relationship of JavaScript code can be tricky. When the ES Module-like syntax doesn’t provide enough tools to describe the exports then you can use namespaces .
For example, you may have complex enough types to describe that you choose to namespace them inside your .d.ts :
To understand how namespaces work in .d.ts files read the .d.ts deep dive.
Optional Global Usage
You can use export as namespace to declare that your module will be available in the global scope in UMD contexts:
To give you an idea of how all these pieces can come together, here is a reference .d.ts to start with when making a new module
Library file layout
The layout of your declaration files should mirror the layout of the library.
A library can consist of multiple modules, such as
These could be imported as
Your declaration files should thus be
Testing your types
If you are planning on submitting these changes to DefinitelyTyped for everyone to also use, then we recommend you:
- Create a new folder in node_modules/@types/[libname]
- Create an index.d.ts in that folder, and copy the example in
- See where your usage of the module breaks, and start to fill out the index.d.ts
- When you’re happy, clone DefinitelyTyped/DefinitelyTyped and follow the instructions in the README.
- Create a new file in the root of your source tree: [libname].d.ts
- Add declare module "[libname]"
- Add the template inside the braces of the declare module, and see where your usage breaks
The TypeScript docs are an open source project. Help us improve these pages by sending a Pull Request ❤
The Declaration Files section is designed to teach you how to write a high-quality TypeScript Declaration File. We need to assume basic familiarity with the TypeScript language in order to get started.
If you haven’t already, you should read the TypeScript Handbook to familiarize yourself with basic concepts, especially types and modules.
The most common case for learning how .d.ts files work is that you’re typing an npm package with no types. In that case, you can jump straight to Modules .d.ts.
The Declaration Files section is broken down into the following sections.
We are often faced with writing a declaration file when we only have examples of the underlying library to guide us. The Declaration Reference section shows many common API patterns and how to write declarations for each of them. This guide is aimed at the TypeScript novice who may not yet be familiar with every language construct in TypeScript.
The Library Structures guide helps you understand common library formats and how to write a proper declaration file for each format. If you’re editing an existing file, you probably don’t need to read this section. Authors of new declaration files are strongly encouraged to read this section to properly understand how the format of the library influences the writing of the declaration file.
In the Template section you’ll find a number of declaration files that serve as a useful starting point when writing a new file. If you already know what your structure is, see the d.ts Template section in the sidebar.
Many common mistakes in declaration files can be easily avoided. The Do’s and Don’ts section identifies common errors, describes how to detect them, and how to fix them. Everyone should read this section to help themselves avoid common mistakes.
For seasoned authors interested in the underlying mechanics of how declaration files work, the Deep Dive section explains many advanced concepts in declaration writing, and shows how to leverage these concepts to create cleaner and more intuitive declaration files.
The Publishing section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages.
For JavaScript library users, the Consumption section offers a few simple steps to locate and install corresponding declaration files.
Читайте также: