DefinitiveTyped имеет определения типов для многих библиотек, но достаточно часто я не могу найти хороший способ использовать их, когда реализация Javascript отделена от Typescript, например, когда библиотека назначает себя свойству окна через
<script src="https://example.com/library.js">
, и когда я управляю пакетом JS, это другой отдельный скрипт. (Даже если объединить все вместе , включая , библиотека является стандартным и надежным методом, предположим, ради вопроса, что у меня нет возможности импортировать библиотеку в мой проект TS.) Например, скажем, я нахожу красивый файл определения для библиотеки с именем myLib
:
// my-lib.d.ts
export const doThing1: () => number;
export const doThing2: () => string;
export const version: string;
export interface AnInterface {
foo: string;
}
export as namespace myLib;
В JS я могу использовать myLib, вызывая window.myLib.doThing1()
и window.myLib.doThing2()
. Как я могу импортировать форму всего объекта window.myLib
, чтобы я мог объявить его как свойство window
? Я вижу, что могу импортировать экспортированные интерфейсы , например:
// index.ts
import { AnInterface } from './my-lib';
const something: AnInterface = { foo: 'foo' };
console.log(something.foo);
Это работает, но я хочу получить доступ к форме фактического объекта библиотеки и значений его свойств (функций и строк и т. Д.), А не только к интерфейсам. Если я сделаю
import * as myLib from './my-lib';
тогда идентификатор myLib
становится пространством имен, из которого я могу ссылаться на экспортированные интерфейсы, но, как и выше, у меня все еще нет доступа к фигурам export const
и export function
из my-lib.d.ts
. (И, конечно, попытка использовать импортированное пространство имен для объявления объекта библиотеки не работает: Cannot use namespace 'myLib' as a type.
Даже если бы я мог это сделать, это не обязательно было бы безопасно, поскольку библиотека, упакованная для браузера, вполне может быть немного отличается от объекта экспорта Node библиотеки)
Если я вручную скопирую и вставлю части d.ts
в свой собственный скрипт, я смогу собрать воедино то, что работает:
// index.ts
declare global {
interface Window {
myLib: {
doThing1: () => number;
doThing2: () => string;
version: string;
};
}
}
Но это грязно, отнимает много времени и, конечно, не правильный способ сделать что-то подобное. Когда я сталкиваюсь с такой ситуацией, я бы вроде смог бы сделать что-то короткое и элегантное, например:
// index.ts
import myLibObjectInterface from './my-lib.d.ts'; // this line is not correct
declare global {
interface Window {
myLib: myLibObjectInterface
}
}
Некоторые файлы определений включают интерфейс для библиотечного объекта, например jQuery, который:
// index.d.ts
/// <reference path="JQuery.d.ts" />
// jQuery.d.ts
interface JQuery<TElement = HTMLElement> extends Iterable<TElement> {
// lots and lots of definitions
Тогда все просто отлично - я могу просто использовать interface Window { $: jQuery }
, но многие библиотеки, изначально не созданные для использования браузером, не предлагают такой интерфейс.
Как уже упоминалось ранее, наилучшим решением будет интеграция библиотеки с проектом TS, позволяющая редактировать и использовать библиотеку и ее типы import
и использовать ее без суеты, но если это невозможно, сделайте У меня остались хорошие варианты? Я мог бы изучить свойства реального библиотечного объекта и добавить интерфейс к файлу определения, который включает в себя все такие свойства и их типы, но при этом необходимо изменить полуканонический файл (ы) определения источника, принятый DT и используемый всеми остальными. неправильно. Я бы предпочел иметь возможность импортировать формы экспорта файла определения и создавать из них интерфейс без изменения исходного файла, но это может оказаться невозможным.
Есть ли более элегантное решение, или файлы определений, с которыми я столкнулся, попросту недостаточно подходят для моей цели и, следовательно, должны быть изменены?