Экспорт одного значения как по умолчанию, так и по именованным экспортам (циркуляр) - PullRequest
0 голосов
/ 13 февраля 2020

Я недавно работал с проектом TypeScript с passport-aut0. Я установил типы для него с помощью файла объявления DefiniteTyped @types/passport-auth0 .

Импорт Strategy в качестве именованного импорта из passport-auth0 работал хорошо (у меня "esModuleInterop": true в моем tsconfig):

import {Strategy} from 'passport-auth0';

Но Strategy также экспортируется по умолчанию export. Итак, как и в файле Readme , вы можете импортировать его следующим образом:

import Strategy from 'passport-auth0';

Это не работает с @types/passport-auth0. Сообщение об ошибке было похоже на

Type 'typeof import("/home/vsts/work/1/s/types/passport-auth0/index")' has no construct signatures.

Я хочу исправить определения типов.

1 Ответ

0 голосов
/ 13 февраля 2020

Я хотел исправить эту проблему для других, и пошел дальше, пытаясь экспортировать / импортировать значение как экспорт по умолчанию, так и именованный экспорт (с подсказками из @ nathan-shively-sanders ).

Мое решение (см. https://github.com/DefinitelyTyped/DefinitelyTyped/pull/42315) оказалось следующим:

Исходные определения типов выглядели примерно так:

//
// The class that will be exported / imported as both:
//
// - name export (works already because `export class`)
// - default export (doesn't work)
//
export class Strategy extends passport.Strategy { /* ... */ }

export interface Profile extends passport.Profile { /* ... */ }
export interface AuthenticateOptions extends passport.AuthenticateOptions { /* ... */ }
export interface StrategyOption { /* ... */ }
export interface StrategyOptionWithRequest extends StrategyOption { /* ... */ }
export interface ExtraVerificationParams { /* ... */ }
export type VerifyFunction = ( /* ... */ ) => void;
export type VerifyFunctionWithRequest = ( /* ... */ ) => void;

Мне пришлось:

  1. переименовать класс с Strategy на StrategyInternal (чтобы при использовании * можно было экспортировать циклическую ссылку без Circular definition of import alias 1021 *)
  2. изменить export перед классом на declare
  3. объявить пространство имен с новым именем StrategyInternal в нижняя часть файла (это называется объединением пространства имен)
  4. переместить все остальные интерфейсы и типы в пространство имен и удалить export s
  5. обновить ссылки внутри класса , например, из. VerifyFunction до StrategyInternal.VerifyFunction
  6. используйте export import внутри пространства имен , чтобы экспортировать значение как именованный экспорт
  7. установить экспорт по умолчанию с export = StrategyInternal внизу файла

Вот суть моего окончательного решения:

declare class StrategyInternal extends passport.Strategy {
    // Updated references to types and interfaces
    // Eg. changing `VerifyFunction` to `StrategyInternal.VerifyFunction`
}

declare namespace StrategyInternal {
    interface Profile extends passport.Profile { /* ... */ }
    interface AuthenticateOptions extends passport.AuthenticateOptions { /* ... */ }
    interface StrategyOption { /* ... */ }
    interface StrategyOptionWithRequest extends StrategyOption { /* ... */ }
    interface ExtraVerificationParams { /* ... */ }
    type VerifyFunction = ( /* ... */ ) => void;
    type VerifyFunctionWithRequest = ( /* ... */ ) => void;

    // NOTE: not true for `export import` statements
    // tslint:disable-next-line:strict-export-declare-modifiers
    export import Strategy = StrategyInternal;
}

export = StrategyInternal;

Я просто хотел опубликовать это как решение, так как оно кажется пройти тесты и разрешить любой из этих стилей импорта ESM (с "esModuleInterop": true в tsconfig):

import {Strategy} from 'passport-auth0';

... или ...

import Strategy from 'passport-auth0';

Если вы не используете взаимодействие с модулями ES, также поддерживаются следующие стили:

import Strategy = require('passport-auth0');

... или ...

import {Strategy} = require('passport-auth0');

или в общем JS в JavaScript:

const Strategy = require('passport-auth0');

... или ...

const {Strategy} = require('passport-auth0');
...