Ссылки Triple Slash Typescript с библиотеками 2.0

У меня есть проект, который изначально был построен на Typescript 1.4.

Он имеет первичную настройку файла, например:

/// <reference path="typedefinitions/jquery/jquery.d.ts" />
/// <reference path="typedefinitions/jqueryui/jqueryui.d.ts" />
/// <reference path="typedefinitions/moment/moment.d.ts" />
module myApp {
   ...
}

Где все остальные файлы просто ссылаются на этот основной файл:

/// <reference path="../mainfile.ts" />
module myApp {
   //more code that can reference anything else in myApp
}

Часть нашего процесса сборки объединяет все файлы машинописного текста нашего приложения вместе, поэтому мы не используем никаких загрузчиков модулей.

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

Взяв, например, ui-router, если я добавлю:

/// <reference path="../node_modules/angular-ui-router/lib/index.d.ts"  />

Упомянутые типы нигде не появляются. Если я сделаю это:

import * as router from 'angular-ui-router';

Тогда все остальные файлы больше не могут ссылаться на «myApp».

Что мне лучше всего сделать для рефакторинга моего выхода из этой ситуации, но при этом иметь возможность скомпилировать все файлы TS в один файл javascript?

Есть ли параметр tsconfig, который я могу изменить? Или что-то еще мне не хватает?


person John    schedule 24.01.2017    source источник
comment
К сожалению, я бы переключился на загрузчик модулей, который собирает для вас файлы, если это возможно. Не стоит бороться с тем, во что превращается JavaScript. Помните, что пакеты из одного файла не будут хорошей вещью, когда http2 будет широко использоваться.   -  person Juan Mendes    schedule 25.01.2017


Ответы (2)


У вас есть несколько вариантов здесь.

Рекомендуемый подход

В наши дни вариант с наименьшими трудностями включает в себя сборщик для обработки ваших потребностей в отдельных файлах и использование модульной системы в стиле ES6 для установления зависимостей (то, что раньше называлось внешними модулями). Насколько мне известно, система пространств имен официально не устарела, но, по моему мнению, судя по сообществу, система пространств имен в основном заброшена. Он несовместим с операторами импорта и системой @types, которые будут использоваться в большинстве примеров и кода, которые вы увидите. Использование этого параметра потребует установления явных зависимостей посредством импорта в каждом файле, а не использования пространств имен в стиле C#.

Затем вы можете использовать что-то вроде systemjs, uglify, browserify и т. д., чтобы пройтись по дереву зависимостей и создать пакет javascript. В принципе, некоторые люди предпочитают это просто для того, чтобы отделить задачу компиляции от минимизации и объединения. Это также решит некоторые проблемы, связанные с неправильным порядком, с которыми вы можете столкнуться при использовании исключительно пространств имен, поскольку каждый файл (модуль) явно указывает свои точные зависимости.

Другие варианты

Вы можете обойтись пространствами имен в краткосрочной перспективе, вручную загрузив файл .d.ts из репозитория DefinitelyTyped (или, конечно, используя типизацию, которую я бы рекомендовал, если вы следуете этому маршруту). Несколько пакетов npm теперь перечисляют пакеты @types в своих зависимостях, поэтому вам может потребоваться установить свойство конфигурации types: [], чтобы убедиться, что ничего из @types не используется, и избежать конфликтов.

Хотя это все еще рабочий вариант, я рекомендую использовать модули ES6. Это не вопрос машинописного текста, сообщество JS очень четко движется в этом направлении, и, как надмножество JS, основные структурные решения JS будут просачиваться в TS, и это станет стандартом. Я чувствую, что пространства имен быстро станут устаревшим кодом, некоторые уже считают пространства имен устаревшими.

person Paarth    schedule 24.01.2017
comment
Моя проблема заключается в том, что ничто на самом деле не ссылается на мои компоненты (все они ссылаются на основное приложение для регистрации в качестве компонентов, но это все - на них ничего не ссылается), они никогда не загружаются SystemJs: как мне обойти это? Нужно ли мне вручную ссылаться на каждый компонент в файле где-то, чтобы зарегистрировать их с помощью angular? - person John; 25.01.2017
comment
@John TBH, как это делает моя компания, но я не в восторге от этого, потому что вам нужно поддерживать изменения в двух местах. Лично я предпочитаю инвертировать его, чтобы компоненты определялись в вакууме, импортировались и регистрировались в определении модуля. Ни один из вариантов не является отличным, последний ближе к подходу angular 2. Я предполагаю, что это было сделано для того, чтобы иметь разумное дерево зависимостей без ручного перечисления всех конечных узлов, чтобы оно хорошо работало с модулями. - person Paarth; 26.01.2017
comment
@John, может быть какой-то способ динамически загружать все модули по определенному шаблону, чтобы загрузчик модулей выполнял блок, даже если он никогда не был включен явно, но я не уверен, что это вообще встроенная функция. Вы можете добиться этого самостоятельно, работая с Ключи системного реестра - person Paarth; 26.01.2017
comment
спасибо за вашу помощь: я только что добавил ответ о том, как я думаю, что собираюсь справиться с ситуацией - person John; 26.01.2017

Паарт, я думаю, что я собираюсь решить эту проблему так же, как это делает angular 2, где я зарегистрирую дочерние компоненты в их родительских компонентах:

привет.component.ts:

import Component from './component.decorator';

@Component('hello', {
    controllerAs: 'vm',
    template: '<div>Hi</div>'
})
export default class HelloComponent { }

app.component.ts:

import Component from './component.decorator';
import HelloComponent from './hello.component';

@Component('app', {
    controllerAs: 'vm',
    directives: [HelloComponent],
    template: `<div>
                <div>{{vm.Message}}</div>
                <hello></hello>
               </div>`
})
export class AppComponent {
    Message: string;

    $onInit() {
        this.Message = 'Hi!!!';
    }
}

component.decorator.ts:

import * as angular from 'angular';
import app from './main';

export interface ComponentBridgeOptions extends ng.IComponentOptions {
    directives?: any[];
}

export default function Component(selector: string, options: ComponentBridgeOptions) {
    return (controller: Function) => {
        app.component(selector, angular.extend(options, { controller: controller }));
    }
}
person John    schedule 26.01.2017