Дополнение объявлений модуля типами из внешнего модуля - PullRequest
2 голосов
/ 14 апреля 2019

Context

Я делаю рендеринг React для NativeScript (то есть библиотеки, которая позволяет объявлять пользовательские интерфейсы NativeScript с помощью React), и я хочу предоставить типизацию для него.

React'sтипизации уже полностью поддерживают React DOM (т. е. повсюду есть ссылки на HTMLElements), но мне нужно расширить наборы, чтобы они также знали об элементах NativeScript.Чтобы обеспечить точную типизацию, мне нужно предоставить ссылки на внешние модули, например, путем импорта ActionBar.Моя попытка выглядит примерно так (что компилирует , но другие модули моего проекта не воспринимают):

// react-nativescript/index.d.ts
import { ActionBar } from "tns-core-modules/ui/action-bar/action-bar";

declare namespace JSX {
    interface IntrinsicElements {
        actionBar: React.ClassAttributes<ActionBar>
          & React.NativeScriptAttributes<ActionBar>
    }
}

declare namespace React {
    interface NativeScriptAttributes<T> {
        className?: string;
        children?: ReactNode;
        onClick?: MouseEventHandler<T>;
    }

// Omitting DetailedNativeScriptFactory<P, T> for brevity.
    interface ReactNativeScript {
        actionBar: DetailedNativeScriptFactory<
            NativeScriptAttributes<ActionBar>,
            ActionBar
        >,
    }
}

Корень проблемы

Добавление импорта верхнего уровня ActionBar изменяет файл с «сценария» на «модуль» :

В TypeScript, как и в ECMAScript 2015, любой файлсодержащий верхний уровень import или export считается модулем.И наоборот, файл без каких-либо объявлений import или export верхнего уровня обрабатывается как сценарий, содержимое которого доступно в глобальной области (и, следовательно, также для модулей).

Дополнительные пояснениятерминологии предоставляется автором TypeScript Мохамедом Хегази .

После его импорта объявления перестают быть доступными для других модулей.То есть я могу использовать тип React.ReactNativeScript только в том случае, если в моем файле отсутствует импорт / экспорт верхнего уровня.В противном случае появляется следующая ошибка:

Пространство имен 'React' не имеет экспортированного члена 'ReactNativeScript'.

ПРИМЕЧАНИЕ: это может быть неправильная конфигурацияс моей стороны tsconfig.json, но я попробовал почти все комбинации tsconfig typeRoots и package.json types на данный момент, и ничто не имеет значения.

(Failing) альтернативный подход

Чтобы сохранить объявления доступными для других модулей, мы можем попытаться переместить импорт ActionBar в сами пространства имен, например:

// react-nativescript/index.d.ts
declare namespace JSX {
    import { ActionBar } from "tns-core-modules/ui/action-bar/action-bar";
    import { ClassAttributes, NativeScriptAttributes } from "react";
    interface IntrinsicElements {
        actionBar: ClassAttributes<ActionBar>
          & NativeScriptAttributes<ActionBar>
    }
}

Однако это приводит к другой ошибке компиляции:

Объявления импорта в пространстве имен не могут ссылаться на модуль

... не говоря уже о сотнях других возникающих в результате ошибок компилятора, в которые я бы не стал копаться.

Известная проблема?

Я нашел эту, казалось бы, связанную проблему: https://github.com/Microsoft/TypeScript/issues/4166

Наш текущий текущий ответ сегодня - "Перенесите ваши материалы в другой .d.ts файл".Это хороший обходной путь, но не отличный.Настоящая наклейка - это когда тип определен во внешнем модуле - невозможно использовать эти типы для расширения глобального интерфейса, даже если это действительно происходит.Это становится еще сложнее, потому что это побуждает людей перемещать типы в глобальное пространство имен, когда они в первую очередь этого не хотят, обостряя проблему.

Я действительно не знаю, что подразумевается подMsgstr "Переместить ваш материал в другой файл .d.ts".Я начал пытаться объявлять все, что мне нужно, в глобальном масштабе (по сути, создавая lib.dom.d.ts для NativeScript), но NativeScript просто слишком велик для такого подхода - и было бы кошмаром, если бы они когда-нибудь обновили свои наборы.

Вопрос

Как я могу дополнить наборы React ссылками на внешние модули, такие как tns-core-modules?

Кажется, что мой первоначальный подход будет работать, если только TypeScript предоставит этот файл всем другим файламв моей библиотеке (и любых проектах, которые ее используют), но независимо от моих настроек tsconfig.json, файл объявлений будет замечен другими модулями, только если это скрипт, а не модуль.

...