microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.11k stars 12.5k forks source link

Remote declaration file #28985

Open kaaninel opened 5 years ago

kaaninel commented 5 years ago

Search Terms

Suggestion

Being able to reference .d.ts files from a remote location

Use Cases

Reference .d.ts files which can match with import "http://example.com/Component1"

Examples

/// <referance path="http://example.com/Definitions/Component1" />
import "http://example.com/Component1"

Checklist

My suggestion meets these guidelines:

DanielRosenwasser commented 5 years ago

Do you have a specific use-case in mind? Contextualizing what you're running into and why current workflows aren't sufficient would be helpful.

saschanaz commented 5 years ago

This would be useful when using remote modules via unpkg without npm installation.

kaaninel commented 5 years ago

Do you have a specific use-case in mind? Contextualizing what you're running into and why current workflows aren't sufficient would be helpful.

I'm developing a client-side library right now and its components are file seperated with es2015 modules. So i want to be able to import remote modules.

import { Slider } from "http://www.mycompany.com/UIKit/"

And this actually works for me but i can't actively using it since there is a red line under every import and basically its type is any so no reason to use typescript with it. I'm currently switching to babel with @babel/typescript preset so i can edit my code in compile time but i want typescript features in my vscode. I want my project to be free of node_modules folder except compiler as much as possible. I hope this clarifies my use-case.

DanielRosenwasser commented 5 years ago

gotcha; in the meantime you could possibly use path mapping, but I understand why this is less-than-desirable.

bradenhs commented 5 years ago

Importing remote modules is where the js community is headed. This is a thing in https://deno.land/ and now browsers are natively supporting this via <script type="module">. I would love to see seamless typescript tooling in these scenarios.

kaaninel commented 5 years ago

I'm new to this repo so i don't really know release cycle. What kinda life cycle these issues have or when we can prototype it ?

luvies commented 5 years ago

Is there going to be anything further on this issue? As @bradenhs says, deno is a thing and there is actually an issue open (denoland/deno#1432) for supporting something like this. One suggestion I had was very similar to the one proposed here, which is something like:

/// @ts-defs https://example.com/definitions/mod.d.ts
import "https://example.com/modules/mod.js"

For deno, the suggestion is now // @deno-defs to prevent using the @ts- space, but if it was natively supported, it would be very useful.

zheeeng commented 5 years ago

I made a solution for it:

  1. Install the types file: yarn add -D @types/Component1
  2. At the project folder, create a declaration file modules.d.ts with content:

    module 'http://example.com/Component1' {
    import content = require('Component1');
    
    export = content
    }
  3. enjoy
    import everything from 'http://example.com/Component1'

We have to have a local declaration for supporting intelligence

jsteuer commented 5 years ago

I have a use case for it. In minimal environments you do not want to use npm or lots of files. Assume you want to edit a single JavaScript file (a script doing calls to an API) with Visual Studio Code. If you can reference remote declaration files (e.g. public git repository with the type declaration of that API) you will benefit from better tool support by only adding a comment on top of that file.

JDrechsler commented 5 years ago

I am currently using the new import maps feature in Google Chrome. This allows me to use the following:

import { h, render, Component } from 'preact';
import Router from 'preact-router';

My import map:

<script type="importmap">
      {
        "imports": {
          "preact": "https://unpkg.com/preact@10.0.5/dist/preact.module.js?module",
          "preact-router": "https://unpkg.com/preact-router@3.1.0/dist/preact-router.es.js"
        }
      }
</script>

I only need the node_modules folder for the declaration files to make VS Code happy. I wish there was a way to fetch the declaration files from some url. Maybe adding it to the tsconfig like so?:

"paths": {
      "preact-router": [
        "https://unpkg.com/preact-router@3.1.0/index.d.ts"
      ]
}

This is just an idea but I could get rid of the node_modules folder entirely this way. To ensure compatibility with other browsers that don't support the import maps yet I could easily have a script that replaces imports with the url found in the import map.

I was thinking about creating an extension for VS Code that would fetch the declaration files on the fly but adding a remote path to some config (tsconfig?) sounds even better.

naivefun commented 3 years ago

Module Federation could be a great scenario?

frehner commented 3 years ago

I, too, am using import maps (through the SystemJS polyfill) and would love a feature like this. When a library is updated, it gets updated in the import-map and is never yarn/npm installed to node_modules, so it seems like a remote URL would be the best solution for that setup.

A couple of questions, however -

(this is with the assumption that TS downloads a copy of the .d.ts file as a local cache - but maybe TS doesn't need to do that?)

jasonwilliams commented 3 years ago

There's a great codepen plugin for VSCode which can pull JS dependencies via the CDN but it looks like types still need to be downloaded. https://github.com/codespaces-contrib/codeswing/issues/25 should be a usecase for this. @JDrechsler what you described in your comment is exactly what i was looking for

qmg-akara commented 3 years ago

Hello all, is there any update on this?

Our use case

We have a React Microfrontend and right now we don't have any type checking/contract testing between Host app and Microfrontend. As a potential solution we are thinking to have a type checking file in both Host and Microfrontend applications. So when we update the Microfrontend props we want to check the remote Host app's props passed down to the Microfrontend in the Microfrontend PR's linting script to see if they match up. Example code:

// This file lives in the Microfrontend app

// These are the props that will be passed down to the Microfrontend from the Host app
import PropsProvidedByHost from 'https://path.to.host.repo/mfeProps.ts';
// These are the props Microfrontend accepting
import PropsAcceptedByMfe from './local/path/to/mfeProps.ts';

(props: PropsProvidedByHost): PropsAcceptedByMfe => props;

So if this file compiles successfully then it means props from Host app provides the minimum required Microfrontend props. This means the new changes will not break the contract between the Host and Microfrontend.

For example this will pass: (props: { id: string }): { id: string } => props; but this will not: (props: { id: string }): { id: number } => props;

And similarly we'll do the same check when the Host app's props (which are passed down to Microfrontend) are changed but this time the remote type file will be the Microfrontend's props type file. Example type checking:

// This file lives in the Host app

// These are the props that will be passed to the Microfrontend from the Host app
import PropsProvidedByHost from './local/path/to/mfeProps.ts';
// These are the props Microfrontend accepting
import PropsAcceptedByMfe from 'https://path.to.host.repo/mfeProps.ts';

// if this passes then props from Host app provides the minimum required Microfrontend props
(props: PropsProvidedByHost): PropsAcceptedByMfe => props;

Example code

We use Webpack Module Federation with React lazy and Suspense to load Micrfrontend and render in the Host app. Example Host app code:

type MFEProps = {
  id: string;
};

const MFE: LazyExoticComponent<ComponentType<MFEProps>> = lazy(
  loadFederatedModule('mfeScope', './MfeModule', `https://path.to/remoteEntry.js`)
);

export default () => (
    <Suspense fallback={<Loading />}>
      <MFE id="some-id"  />
    </Suspense>
);
BahaaZidan commented 3 years ago

Are there any updates regarding this issue ? I'm trying to implement micro-frontends and having the ability to fetch declaration files over network will allow me to be type-safe when using cross-dependencies.

kaaninel commented 3 years ago

Deno deals with this partially but afaik on typescript side there is no development so far. @BahaaZidan

pixelamit commented 3 years ago
```ts
module 'http://example.com/Component1' {
  import content = require('Component1');

  export = content
}

enjoy

import everything from 'http://example.com/Component1'

Hi , I am trying to share common logic via Single-spa utility.Can you please guide me how can i share my common code using this method.Any workig POC link would be great!!

Really Appreciate your help

alshdavid commented 1 year ago

I write client scripts that I embed into websites using tamper monkey or similar user script injection techniques.

To keep overhead low, I have a library of utilities (like waitForElement()) which I compose into larger website-specific scripts.

I tend to start out writing these composed scripts in the browser debug console, importing utilities as I need them - then as my use case gets more advanced I will copy/paste everything into vscode and go from there.

Due to the fact that my utility scripts are all located on a remote http URL and my client script doesn't have a build step - I get no type information in the IDE.

It would be nice if the language server could resolve remote .js files and at least obtain type information from JSDoc, or at best look for an adjacent d.ts file with type information.