How to not specify file type as .js in a .ts file?

Viewed 160

My goal is to import .ts file as it is instead of specifying the file type as .js e.g import {acccessRights} from "utils/accessRights".

My expected result: I can import a method from other file without specifying the file type.

My actual result: It throws error GET http://127.0.0.1:5501/build/lights/switchLights net::ERR_ABORTED 404 (Not Found).

Temporary solution: specify the file type as .js e.g import { switchLights } from "lights/switchLights.js". However, the jest will break because it does not find the .js file.

part of index.html

<body>
  <script type="module" src="app.js"></script>
</body>

part of app.ts

import { User } from "./utils/accessRights";
import { switchLights } from "./lights/switchLights";

utils/accessRights.ts

export interface User {
  role: string;
}

export function userIsAdmin(user: User): boolean {
  return user.role === "admin";
}

lights/switchLights.ts

import {User, userIsAdmin} from "../utils/accessRights";

let lightsCondition: boolean = false;

function switchLightsRender() {
  document.getElementById("lightsCondition").innerHTML = lightsCondition ? "ON" : "OFF";;
  document.getElementById("lightsButton").innerHTML = `Lights ${!lightsCondition ? "ON" : "OFF"}`;
}

export function switchLights(user: User) {
  if (!userIsAdmin(user)) return false;
  lightsCondition = !lightsCondition;
  switchLightsRender();
  return true;
}

These are the jest files for the unit tests.

test/utils/accessRights.test.ts

import {userIsAdmin, User} from "../../src/utils/accessRights";

export let userTest: User = { role: "admin" }

test('user is admin', () => {
  expect(userIsAdmin(userTest)).toBe(true);
})

test/lights/switchLights.ts

import {userTest} from "../utils/accessRights.test";
import {switchLights} from "../../src/lights/switchLights";

test("lights switched ON/OFF", () => {
  let lightsConditionRef = document.createElement("span");
  lightsConditionRef.setAttribute("id","lightsCondition");
  document.body.appendChild(lightsConditionRef);

  let lightsButtonRef = document.createElement("button")
  lightsButtonRef.setAttribute("id","lightsButton");
  document.body.appendChild(lightsButtonRef);
  
  expect(switchLights(userTest)).toBe(true);
})

This is one of the transpiled .ts file to a .js file

The issue is that the auto generated code does not specify the file type in the import

My expected result:

import { userIsAdmin } from "../utils/accessRights.js";

My actual result:

import { userIsAdmin } from "../utils/accessRights";

This is the auto generated file.

build/lights/switchLight.js

import { userIsAdmin } from "../utils/accessRights";
var lightsCondition = false;
function switchLightsRender() {
    var lightsConditionRef = document.getElementById("lightsCondition");
    if (lightsConditionRef !== null)
        lightsConditionRef.innerHTML = lightsCondition ? "ON" : "OFF";
    ;
    var lightsButtonRef = document.getElementById("lightsButton");
    if (lightsButtonRef !== null)
        lightsButtonRef.innerHTML = "Lights " + (!lightsCondition ? "ON" : "OFF");
}
export function switchLights(user) {
    if (!userIsAdmin(user))
        return false;
    lightsCondition = !lightsCondition;
    switchLightsRender();
    return true;
}
1 Answers

This is your issue: How to make TypeScript output valid ES6 module import statements?

Solution:

Use a bundler. I'd suggest using parcel for now, mostly because it doesn't require any setup.

If you need to configure a lot of things and have edge cases, I would recommend using webpack.

Installing parcel

  1. npm i -D parcel
  2. Actually change the import in your HTML file form app.js to app.ts (or whatever your file is called).
  3. Add an npm script to develop:
"scripts": {
  "serve": "parcel index.html"
},
  1. run npm run serve

This will host a server for you (URL in the terminal) and recompile if you change anything.

Parcel Documentation(Getting Started)

Related