I'm translating this javascript project (https://github.com/Legorin/satisfactory-calculator) to typescript.
I'm getting an error when I import the transpiled typescript file in a html script tag.
<script>
var handlers = {}
</script>
<script type="module">
import { Initilatizion } from "./init.js";
handlers.init = Initilatizion.init;
</script>
The error is: Uncaught SyntaxError: The requested module './init.js' does not provide an export named 'Initilatizion'
Here is my init.ts file
import { Belt } from "./belt";
import { Building } from "./building";
import { FactorySpecification } from "./factorySpecification";
import { Fragment } from "./fragment";
import { Item } from "./item";
import { Recipe } from "./recipe";
import { Settings } from "./settings";
// tslint:disable-next-line: no-var-requires
const d3 = require("../third_party/d3.min.js");
export class Initilatizion {
public static loadData(settings) {
const spec: FactorySpecification = FactorySpecification.getInstance();
d3.json("data/data.json").then((data) => {
const items = Item.getItems(data);
const recipes = Recipe.getRecipes(data, items);
const buildings = Building.getBuildings(data);
const belts = Belt.getBelts(data);
spec.setData(items, recipes, buildings, belts);
Settings.renderSettings(settings);
spec.updateSolution();
});
}
public static init() {
const settings = Fragment.loadSettings(window.location.hash);
this.loadData(settings);
}
}
Here is my tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"allowJs": true,
"outDir": "dist",
"sourceRoot": "src",
},
}
Where is my mistake?
You declared the wrong module type in your tsconfig.json!
By setting module to "commonjs" you tell typescript to generate a JavaScript file that uses the commonjs import/export syntax used by nodejs and others.
You however, use the "new" ES6-module import/export syntax in your HTML and therefore have to set module to "esnext" or "es6"!
Related documentation
Note: You shared an invalid tsconfig.json file, I fixed it below
Example tsconfig.json:
{
"compilerOptions": {
"module": "es6",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"allowJs": true,
"outDir": "dist",
"sourceRoot": "src"
},
}
Related
I have a TS project with the following configuration:
tsconfig.json (partial)
{
"compilerOptions": {
"module": "commonjs",
"baseUrl": "src",
"esModuleInterop": true,
},
"include": [
"src"
]
}
I have a dependency on the stripe NPM package:
{
// ...
"dependencies": {
"stripe": "^8.45.0",
}
}
Then I have the following files:
src/routes/payments/index.ts
src/stripe/index.ts
I am having some trouble with imports in src/routes/payments/index.ts. I want to import the stripe library, not my own code.
This works:
// Uses me the 'Stripe' constructor which is the default export from the package
const stripe = require('stripe')('KEY');
This does not work:
import Stripe from 'stripe';
const stripe = new Stripe('KEY');
I get the following error:
Module '"PROJECT/src/stripe/index"' has no default export.
How do I disambiguate and tell TS I want to use stripe from node_modules?
Can you try to update the tsconfig.json file like this:
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*",
"src/*"
]
}
}
}
I am trying to export/import an interface in Typescript but I am getting this error, I am not sure what I am doing wrong here
Uncaught SyntaxError: The requested module '/src/types/settings.ts' does not provide an export named 'Settings'
In my types/settings.ts I have this
export interface Settings {
activeUser: number
}
And I import it like this
import { Settings } from '#/types/settings'
And here is my tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"baseUrl": "./src/",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"paths": {
"#/*": ["src/*"],
},
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"isolatedModules": false
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
I am using Vue/Vite with Typescript
It is weird that npm run build will work fine, but npm run dev will throw SyntaxError.
I was forced to use import type { ... which in consequence also required same touch for Ref from vue.
Workaround was posted on GitHub for Vite issue 731
Entries in paths are resolved relative to baseUrl. Try this:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/*": ["src/*"]
}
}
}
… or this:
{
"compilerOptions": {
"baseUrl": "./src/",
"paths": {
"#/*": ["./*"]
}
}
}
In plain JS we can use import statements with data uri, e.g.:
import { number, fn } from 'data:text/javascript;charset=utf-8;base64,ZXhwb3J0IGNvbnN0IG51bWJlciA9IDQyOwpleHBvcnQgY29uc3QgZm4gPSAoKSA9PiAiSGVsbG8gd29ybGQiOw==';
Or dynamically:
import('data:text/javascript;charset=utf-8;base64,ZXhwb3J0IGNvbnN0IG51bWJlciA9IDQyOwpleHBvcnQgY29uc3QgZm4gPSAoKSA9PiAiSGVsbG8gd29ybGQiOw==')
.then(module => console.log(module));
However, putting the same code in a typescript file gets us a "Cannot find module" error.
My tsconfig.json is as follows:
{
"compilerOptions": {
"module": "esnext",
"lib": [
"esnext",
"es6",
"dom"
],
"moduleResolution": "node",
"outDir": "./build",
"noImplicitAny": false,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"target": "es6",
"jsx": "react"
},
"include": [
"src/**/*", "../addon/build/background.js"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
Typescript docs on module resolution have no mention of data:... from what I see. Is there a way to get this to work in typescript?
See Wildcard module declarations in the Typescript handbook.
You could do something like this:
// types.d.ts
declare module "data:text/javascript;*" {
export const number: number;
export function fn(): string;
}
// index.ts
/// <reference path="types.d.ts"/>
import { number, fn } from 'data:text/javascript;charset=utf-8;base64,ZXhwb3J0IGNvbnN0IG51bWJlciA9IDQyOwpleHBvcnQgY29uc3QgZm4gPSAoKSA9PiAiSGVsbG8gd29ybGQiOw==';
This tells Typescript that an import matching the data:text/javascript; prefix will expose a number property (as a number type) and an fn property (which returns a string). Adjust the module declaration to fit your importer semantics as appropriate.
I have a file named constants.ts which contains constants related to my React TypeScript application.
The file looks like this:
// The error for when errors are bad.
const BAD_ERROR_ERROR = "Something happened that shouldn't have. Please contact an admin";
const Constants = {
APIResponses: {
accounts: {
login: {
account_not_verified: {
message: "You need to verify your email",
problemFields: ["email"]
},
bad_login: {
message: "Your email or password is incorrect",
problemFields: ["email", "password"]
},
default: {
message: BAD_ERROR_ERROR,
problemFields: ["email", "passwords"]
}
}
}
}
};
export default Constants;
I then import it in a TSX file like this:
import Constants from "constants";
and reference a key like this:
const { status } = json;
const resp = Constants.APIResponses.accounts.login[status.message];
However, when I attempt to use it, I get this error:
Property 'APIResponses' does not exist on type 'typeof import("constants")'. TS2339
69 |
70 | const { status } = json;
> 71 | const resp = Constants.APIResponses.accounts.login[status.message];
This error only occurs when importing it from my baseDir as "constants", when importing as ../../constants, it works fine. (That's the work around I'm going with right now)
Here's the things I've tried that haven't worked:
Explicitly defining a type for Constants in constants.ts
Renaming it to constants.js
Casting the type on the default export
Not exporting it as default
Here's the hacky fixes I found that work, but are hacky and undesirable:
Importing it relatively (../../constants) (current)
Casting it to an any type ((Constants as any).APIResponses...)
Here's my tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react",
"rootDir": "./src",
"baseUrl": "./src"
},
"include": [
"src"
]
}
How can I extend third-party declaration files?
for example, I want to extend Context from #types/koa and add an extra field(resource) to it.
I tried this:
// global.d.ts
declare namespace koa {
interface Context {
resource: any;
}
}
But it doesn't work:
error TS2339: Property 'resource' does not exist on type 'Context'.
Update
a simplified version of my code which produces this error:
import {Context} from 'koa';
import User from './Models/User';
class Controller {
async list(ctx: Context) {
ctx.resources = await User.findAndCountAll();
ctx.body = ctx.resources.rows;
ctx.set('X-Total-Count', ctx.resources.count.toString());
ctx.status = 200;
}
}
typescript v2.4
// tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"exclude": [
"node_modules"
]
}
You have to use module augmentation as described here:
import { Context } from "koa";
declare module "koa" {
interface Context {
resource: any;
}
}