2016-04-12 3 views
0

У меня есть файл my-module.ts:машинописи вопрос о подписи вызова

declare module "my-module" { 
    interface main { 
     (string):string, 
     methodName():any, 
     propertyName:any, 
     objectName:Object 
    } 
    export default main; 
} 

и при использовании его из файла test.ts:

import * as MyModule from "my-module"; 
var s = MyModule('test'); 

Я получаю ошибку Cannot invoke an expression whose type lacks a call signature.

Почему это происходит, и как это исправить?

UPDATE

По предложению от Джо Клэй, если мы изменим код так:

declare module "my-module" { 
    interface main { 
     (string):string, 
     methodName():any, 
     propertyName:any, 
     objectName:Object 
    } 
    var myModule: main; 
    export default myModule; 
} 

, а затем попытаться использовать его как это:

import myModule from "my-module"; 
var s = myModule('test'); 

Он генерирует следующий JavaScript:

var my_module_1 = require("my-module"); 
var s = my_module_1["default"]('test'); 

Какая ошибка my_module_1.default is not a function.

UPDATE

Следующая перемена решить непосредственную проблему:

declare module "my-module" { 
    interface main { 
     (string):string, 
     methodName():any, 
     propertyName:any, 
     objectName:Object 
    } 
    var myModule: main; 
    export = myModule; // <= Here's the change 
} 

и использовать его:

import * as myModule from "my-module"; 

Однако это подарил мне еще одну проблему. Я показал упрощенный пример my-module, в то время как у реального есть несколько классов и enum-s для экспорта. Однако с изменением, как выше, мы больше не можем этого делать.

Окружающие классы и enum -s предполагается экспортировать с помощью export enum Name{} и export class Name, но этот синтаксис отвергнут при export = myModule используется, производя ошибку: An export assignment cannot be used in a module with other exported elements..

Как исправить это сейчас? :)

Еще больше проблем, у меня есть еще один модуль, который имеет свойство типа my-module, для которого, если я объявляю properName: MyModule, я получаю Cannot find name 'pgMinify'. Я не понимаю, что это значит.

ответ

2

a) Если у вас есть экспорт по умолчанию, синтаксис импорта равен import MyModule from "my-module"; - вам не нужен * as.

b) Вы не можете вызвать интерфейс. Вы можете назвать что-то, что реализует, но попытка сделать MyModule() не имеет смысла.

EDIT:

В ответ на обновленный код - this is a pretty common issue when you're trying to use TypeScript's ES6 imports with a CommonJS module.Microsoft настаивает на том, чтобы придерживаться спецификации там, где это возможно, вместо того, чтобы использовать какие-либо магии для преобразования module.exports в экспорт ES6 по умолчанию - технически они, вероятно, верны в этом, но при условии, что Babel (вероятно, самый популярный транспилер JavaScript) делает преобразование просто отлично, я действительно хочу, чтобы они просто добавили его в TypeScript.

Рекомендуемый способ обойти это вернуть ваш импорт синтаксису import * as MyModule from "my-module"; и изменить объявление следующим образом:

declare module "my-module" { 
    interface main { 
     (string):string, 
     methodName():any, 
     propertyName:any, 
     objectName:Object 
    } 
    var myModule: main; 
    export = myModule; // <= Here's the change 
} 

Надеюсь, это даст вам результат, который вы ищете.

EDIT 2:

Это становится немного более сложным, если вы хотите, чтобы начать определять свои собственные типы в вашей декларации, а не только примитивы - но не намного сложнее. Хорошим примером для этого является the type definitions for body-parser. Я не буду копировать всю вещь здесь, как и мой ответ уже все с ума долго, но вещи, чтобы отметить следующие:

  • Вы можете объявить namespace, есть, что в качестве основного экспорта, а затем экспорт другие вещи изнутри.
  • В объявлениях слияния можно связать объявления, отметив, что они определяют bodyParser как функцию, а затем определяют пространство имен с тем же именем. Они будут объединены, что означает, что экспорт в пространстве имен будет отображаться как свойства функции (например, будут доступны bodyParser() и bodyParser.json()).

В основном, лучший совет, который я могу дать вам, чтобы просмотреть хранилище DefinitelyTyped для модулей, которые вы хорошо знаете, и посмотрим, как были созданы их определения - это лучший способ узнать, как сделать это самостоятельно.

+0

Это эмбиентное объявление для существующего модуля Node.js, написанного на JavaScript. Как иначе это должно быть объявлено тогда? –

+0

@ vitaly-t: Вам нужно экспортировать что-то, что реализует ваш 'main' интерфейс, а сам интерфейс, я думаю? Итак, что-то вроде 'var myModule: main; экспортировать default myModule; '. –

+0

Если я это сделаю, код компилируется, но он генерирует это: «var my_module_1 = require (« my-module »); var s = my_module_1 ["default"] ('test'); 'который затем выбрасывает с' my_module_1.default, не является функцией'. –

Смежные вопросы