-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathREADME.md
146 lines (106 loc) · 8.08 KB
/
README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# Создание type definition для umd модуля на основе пространств имен
## Метод 1 (весьма сомнительный)
> Метод использует обратную компиляцию JavaScript программы, что требует наличия файлов типизации внешних библиотек. Можно попробовать применить заглушку следующего вида: `declare var React: any;`
Оригинальное руководство размещено [тут](https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html). Попробуйте применить следующий конфиг для TypeScript Compiler:
```
{
// Change this to match your project
include: ["src/**/*"],
compilerOptions: {
// Tells TypeScript to read JS files, as
// normally they are ignored as source files
allowJs: true,
// Generate d.ts files
declaration: true,
// This compiler run should
// only output d.ts files
emitDeclarationOnly: true,
// Types should go into this directory.
// Removing this would place the .d.ts files
// next to the .js files
outDir: "dist",
},
}
```
Тот же конфиг можно передать без дополнительного файла напрямую из командной строки:
```
npx typescript src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types
```
### Примечание:
Скорее всего, вы получите весьма скудную отписку, поэтому я бы рекомендовал сразу начинать со второго метода...
```
declare const _exports: any;
export = _exports;
export var material: any;
```
Возможно, если подаваемый на вход файл `*.js` будет содержать комментарии JSDoc, мы получим что-то ценное, но это грабли, из-за который не выстрелил `google-closure-compiler`
## Метод 2 (применен в `material-ui-umd`)
> Метод основан на получении информации времени исполнения и обработки JavaScript программы как текста, сторонние файлы типизации не требуются
В репозитории в папке /assets/js лежат два скрипта: `generate-closure-externs.js` и `generate-typescript-entries.js`. Они подключаются непосредственно в `index.html`. Первый из них добавляет в глобальный контекст функцию `externs()`, которая имеет один входной параметр позволяет генерировать из umd модуля в глобальном объекте основу для файлов описания типов [Google Closure Compiler](https://developers.google.com/closure/compiler). Они имеют следующее содержание:
```
/**
* @fileoverview Externs for core generated by generate-closure-externs in browser runtime
* @see https://gist.github.com/tripolskypetr/ed33439520b59c5077cbdf5d0ff4ea62
* @externs
*/
var core = {colors:{common:{black:function() { },white:function() { }},red:{
```
Обычно, внутри лежит одна переменная - объект, поля которого либо такие же объекты, либо функции. К ним можно наслаивать JSDoc комментарии, Однако, нам он потребуется исключительно для передачи в функцию `tsEntries()` из второго скрипта. Функция запросит клик по документу и выдаст диалоговое окно выбора сгенерированного на первом этапе файла описания Google Closure Compiler. Выходной файл будет иметь следующий вид:
```
/**
* @fileoverview Typedefs for material generated by generate-typescript-entries in browser runtime
* @see https://gist.github.com/tripolskypetr/b9c56202cd98935a49389fb46f77ef19
*/
declare namespace material{export class core{}export class icons{}export class styles{}export class system{}}
```
Над ним рационально применить prettier, команда будет иметь следующий вид: `prettier --write system.d.ts`, а после внимательно посмотреть: обычно, генератор угадывает типы объектов исходя из их вложенности, но иногда назначение типа нужно править мануально. Угадывание происходит по следующему принципу:
![generator](../../assets/img/generator.png)
- Нет потомков: функции (методы)
- Один потомок: интерфейсы (классы)
- Более одного: пространства имен
## Метод 3
> TypeScript позволяет создать прослойку между ES6 модулями и пространствами имен. Делается это следующим способом:
Рассмотрим на примере [mobx-react-lite](../../type/[email protected]) из файлов описания типов в этом репозитории.
**Было:**
```
import "./utils/assertEnvironment";
export { isUsingStaticRendering, enableStaticRendering } from "./staticRendering";
export { observer, IObserverOptions } from "./observer";
export { Observer } from "./ObserverComponent";
export { useLocalObservable } from "./useLocalObservable";
export { useLocalStore } from "./useLocalStore";
export { useAsObservableSource } from "./useAsObservableSource";
export { resetCleanupScheduleForTests as clearTimers } from "./utils/reactionCleanupTracking";
export declare function useObserver<T>(fn: () => T, baseComponentName?: string): T;
export { isObserverBatched, observerBatching } from "./utils/observerBatching";
export declare function useStaticRendering(enable: boolean): void;
```
**Стало:**
```
import * as staticRendering from "./staticRendering";
import * as observer from "./observer";
import * as ObserverComponent from "./ObserverComponent";
import * as useLocalObservable from "./useLocalObservable";
import * as useLocalStore from "./useLocalStore";
import * as useAsObservableSource from "./useAsObservableSource";
import * as reactionCleanupTracking from './utils/reactionCleanupTracking';
import * as observerBatching from './utils/observerBatching';
declare global {
export namespace mobxReactLite {
export const isUsingStaticRendering = staticRendering.isUsingStaticRendering;
export const enableStaticRendering = staticRendering.enableStaticRendering;
export const observer = observer.observer;
export const IObserverOptions = observer.IObserverOptions;
export const Observer = Observer.ObserverComponent;
export const useLocalObservable = useLocalObservable.useLocalObservable;
export const useLocalStore = useLocalStore.useLocalStore;
export const useAsObservableSource = useAsObservableSource.useAsObservableSource;
export const clearTimers = reactionCleanupTracking.resetCleanupScheduleForTests;
export declare function useObserver<T>(fn: () => T, baseComponentName?: string): T;
export const isObserverBatched = observerBatching.isObserverBatched;
export declare function useStaticRendering(enable: boolean): void;
export const observerBatching = observerBatching.observerBatching;
} // namespace mobxReactLite
} // declare global
```
Этот способ был успешно применен в [mobx-app](../../packages/mobx-app). **Обратите внимание:** в директории `type` находятся именно поддиректории вида `[email protected]` с файлами `index.d.ts`, это важно, TypeScript Compiler ищет именно файлы index...