When extending the Express.Request interface in TypeScript I ran into this problem that I want to use an external library definition, but I can't import the external library as it results in error ->
Error:(4, 28) TS1147: Import declarations in an internal module cannot reference an external module.
Edit: It is a .d.ts file
/// <reference path="../typings/express/express.d.ts" />
declare module Express {
import bunyan = require('bunyan'); <-- results in error
export interface Request {
_id: string; <-- this works
log: bunyan.Logger; <-- Here I want to define that it is bunyan.Logger instance;
}
}
Trying to reference the bunyan.d.ts (https://github.com/borisyankov/DefinitelyTyped/blob/master/bunyan/bunyan.d.ts)
Also results in a problem, as the bunyan module is exported as string
declare module "bunyan" {
...
}
As such trying to use it from reference results in not found.
/// <reference path="../typings/express/express.d.ts" />
/// <reference path="../typings/bunyan/bunyan.d.ts" />
declare module Express {
export interface Request {
_id: string;
log: bunyan.Logger; <- Error:(8, 18) TS2304: Cannot find name 'bunyan'.
}
}
tl;dr; How to extend interface definition with external module definitions.
I don't think you can add to an existing interface when a require is necessary, but you can extend the existing interface using the extends keyword.
Move your import statement outside your module, export your module, and extend the existing interface:
import bunyan = require('bunyan');
import express = require('express');
export declare module ExtendedExpress {
export interface Request extends express.Express.Request {
_id: string;
log: bunyan.Logger;
}
}
Then you have to import this module where you want to use it.
The referencing of internal and external modules will be improved in v1.5 which is currently in an alpha release (http://blogs.msdn.com/b/typescript/archive/2015/03/27/announcing-typescript-1-5-alpha.aspx).
In the meantime you can import in your bunyan module via:
var bunyan = require('bunyan');
Related
I'm trying to use the npm package 'vuex-orm-decorators' from https://github.com/scotley/vuex-orm-decorators#readme
When I try to insert into the DB, I get the error TypeError: this.types is not a function
Entity looks like this
import { Model } from "#vuex-orm/core";
import { NumberField, OrmModel, StringField } from "vuex-orm-decorators";
#OrmModel("races")
export default class Race extends Model {
#NumberField()
public ID!: number;
#StringField()
public Name!: string;
}
store looks like this:
import Vue from "vue";
import Vuex from "vuex";
import { ORMDatabase } from "vuex-orm-decorators";
Vue.use(Vuex);
export default new Vuex.Store({
.
.
.
plugins: [ORMDatabase.install()]
});
Also, maybe this is a clue.... in Vuex-Orm, this.setters is returning a value, but this.setters('all') is returning undefined.
/**
* Get all records.
*/
Model.all = function () {
return this.getters('all')();
};
From seeing the undefined basic fields and functions, it seems like the vuex-orm database isn't getting set up correctly. Any ideas?
I tried to create a stackoverflow tag for vuex-orm-decorators, but I'm not quite at 1500 rep yet, so I just tagged it as vuex-orm.
There is a small bug in vuex-orm-decorators package in the implementation of the types function defined in Vuex-ORM Single Table Inheritance docs.
I've created a fork in which I fixed this simple problem and created a pull request to update the original package.
Lastly, I've to point that from my tiny dive into this package that it isn't fully ready yet for table inheritance features built in Vuex-ORM but still is great for simple use cases.
I need help to understand how to use the abstract class org.apache.commons.math3.linear.RealVector of java.lang.Object in my program.
I have three classe, that should be using it. A Point, a Simplex and a Triangle.
The Simplex-Class should use the methods of the RealVector class to calculate the perimeter of an object, like triangle.
import java.lang.Object.*;
package org.apache.commons.math3.linear;
import org.apache.commons.math3.linear.RealVector.Entry;
import org.junit.Assert;
public class Point
{
private int dimension;
private double[] values;
private RealVector rv;
public Point(int d, double... values) {
try {
this.dimension = d;
this.values = values;
} catch (IllegalArgumentException ex) {
System.out.println("Bad Arguments");
}
}
public double get (int i) {
return values[i];
}
public int dim() {
return dimension;
}
}
When I compile that I get an error:
You have changed the package statement to a package which does not
exist in this project.
So the question is: how to use the RealVector class in my program?
Let's focus on the first lines of your code:
import java.lang.Object.*;
package org.apache.commons.math3.linear;
import org.apache.commons.math3.linear.RealVector.Entry;
import org.junit.Assert;
It has many problems:
The package declaration must come before the imports
You shouldn't put your own class into the package org.apache.commons.math3.linear. Put it inside your own package, named after your company/organization. You're not writing for the apache foundation.
import java.lang.Object.*; makes no sense. Object is a class, not a package. So you can't import all the classes inside java.lang.Object. And you don't need to import any class from java.lang: they're imported implicitly.
import org.apache.commons.math3.linear.RealVector.Entry;: you're never using this Entry class in your class. You're using the RealVector class, so that's the class you should import (although you're not really using it: you just have a private fiel of that type, which is never initialized not read, and is thus useless).
import org.junit.Assert;: you're not using this Assert class in your code either, so it shouldn't be imported. That class, BTW, is used to implement unit tests. It should be imported in unit tests, but not in production classes.
Start by fixing all this, and then ask aother question if you still have a compilation error, mentioning the exact and complete error. Make sure the jar file of the math3 apache library is in the classpath of your project: it's not bundled with the JDK, so you need to add it to the project.
I have this namespace
namespace Validation {
export function Func1() {
// code
}
export function Func2() {
// code
}
}
Which I can import in my app.ts:
import Validations = Validation;
But when I want to reference some modules in my Validation namespace
import {Request, Response} from 'express';
var jwt = require('jsonwebtoken');
var express = require('express');
import {Config} from './../config';
namespace Validation {
export function Func1() {
// code
}
export function Func2() {
// code
}
}
So then import Validations = Validation; in my app.ts giving me an error cannot find namespace Validation.
Why it is happened? Any thoughts how to fix?
UPDATE 1 : In case if I put imports after namespace I am getting an error Import declaration in a namespace cannot import a module:
namespace Validation {
import {Request, Response} from 'express'; //Error: Import declaration in a namespace cannot import a module
var jwt = require('jsonwebtoken');
var express = require('express');
import {Config} from './../config'; //Error: Import declaration in a namespace cannot import a module
export function Func1() {
// code
}
export function Func2() {
// code
}
}
my config.ts is just a simple class:
export class Config {
public static get Secret():string { return 'stuff'; }
public static get Database():string { return 'mongodb://127.0.0.1:27019/test'; }
}
And 'express' it is an npm package
UPDATE 2
I think I just fixed config by wrapping it in to namespace:
namespace Common {
export class Config { .. }
}
Also changed import statement from this import {Config} from './config'; to this: import Config = Common.Config; but haven't yet figure out how to fix 'express' thing
This happens because from the moment you put a top-level import or export statement into a file, that file is treated as an external module itself. If you are using internal modules (namespaces), I suggest importing inside namespaces, so that there are no top-level import or export statements.
namespace Validation {
import Request = ...;
import Response = ...;
export function Func1() {
// code
}
export function Func2() {
// code
}
}
The other approach would be to use external modules instead, but that requires a module loading system, which might be superfluous in many cases.
Right now, you are mixing internal and external modules, which is not recommended. Regarding complex structural cases like this, Typescript is still very far from being a mature language.
I assume that you have defined your validation functions in the separate (from app.ts) file. If this is the case then what you need to do is:
In your Validation.ts:
export function Func1() {
// code
}
export function Func2() {
// code
}
In your app.ts:
import * as Validation from './Validation';
Validation.Func1();
Your problem is most likely in mixing together concepts of modules and namespaces in typescript. Have a look here: Namespaces and Modules, and be sure to look through Modules and Namespaces
I have a class which I want to have some optional nested properties.
class Input {
stuff {
first_name?: string; // optional
};
however it seems that isn't legal typescript. ; expected
Next is to pull stuff out into an interface
interface IFrom {
id: any;
first_name?: string;
};
class Input {
from:IFrom;
however when i put these in the same file I get
tsPublic property 'from' of exported class has or is using private name 'IFrom'.
I can't make public interface
'public' modifier cannot appear on a module element.
What I've ended up doing is putting the interface in yet another file, but this is getting to be astronaut engineering where every struct and property needs to be in its own file...
Am I missing something about how best to do this?
I want the first_name property to be public but part of a struct.
Want it to be optional.
Prefer fewer individual files.
Thanks!
however it seems that isn't legal typescript. ; expected
The syntax for inline types is incorrect. You are missing a :. The following works fine:
class Input {
stuff: {
first_name?: string; // optional
};
}
That answers the question. But since you tried more stuff:
Public property 'from' of exported class has or is using private name 'IFrom'.
You probably have export class ... that means that you need to do export interface too to export any interface that the class uses.
You should use the keyword export with interfaces and classes, not public.
Here is an example:
module ModuleA {
export interface IFrom {
id: any;
first_name?: string;
}
}
module ModuleB {
export class Input {
from:ModuleA.IFrom;
}
}
var input = new ModuleB.Input();
input.from = {id: 123, first_name: 'Bob'};
alert(input.from.first_name); // Bob
EDIT:
Put another way the following within a .d.ts file shouldn't produce compiler error TS2137 'Class "MyClass" does not implement interface "IInterface"':
interface IInterface {
someMethod():void;
}
declare module "mod" {
export class MyClass implements IInterface {
constructor();
}
}
because I'm not (and can't in a declaration) implementing anything. Is this a bug in the compiler or is there some other way/syntax to do what the above implies? I would think the compiler smart enough to know to precisely include IInterface's signature as part of MyClass, and not require its methods be redeclared.
ORIGINAL:
I'm trying to write a d.ts for the node component bunyan. Having a problem with exporting a class that implements an external interface, specifically RingBuffer which extends node's EventEmitter. The problem simplified is (below in a bunyan.d.ts file):
// this interface declared in <reference..., put inline here for simplicity
interface IExternal {
inheritedMethod():void;
}
interface RingBuffer extends IExternal {
write():void;
}
declare var RingBuffer: {
new():RingBuffer;
}
declare module "bunyan" {
export var RingBuffer;
}
then used in myNodeApp.js
/// <references path="bunyan.d.ts" />
import bunyan = require( 'bunyan' );
var rb = new bunyan.RingBuffer();
// compiler doesn't error on this; thinks RingBuffer is type any.
// also, no intellisense to show write() method.
rb.badFunc();
changing bunyan.d.ts to:
declare module "bunyan" {
export class RingBuffer { constructor(); }
}
compiles, but same problem when used; no intellisense, no compile errors.
changing bunyan.d.ts to
declare module "bunyan" {
export var RingBuffer:RingBuffer;
}
causes compile error in myNodeApp.js
// error TS2083: Invalid 'new' expression
import rb = new bunyan.RingBuffer();
removing from bunyan.d.ts
declare module "bunyan" {
...
}
causes compile error in myNodeApp.js
// error TS2071: Unable to resolve external module ''bunyan''
import bunyan = require( 'bunyan' );
changing bunyan.d.ts
interface IExternal {
inheritedMethod():void;
}
interface IRingBuffer extends IExternal {
}
declare module "bunyan" {
export class RingBuffer implements IRingBuffer {}
}
cause compile error
// error TS2137: Class "bunyan".RingBuffer declares interface IRingBuffer but
// does not implement it: type '"bunyan".RingBuffer' is missing property
// 'inheritedMethod' from type 'IRingBuffer'
implying I have to redeclare all inherited methods from all extended interfaces, besides IRingBuffer, which seems a bit ridiculuous to have to do in a d.ts file
Does anyone know the 'correct' way to declare an ambient class that implements an interface for consumption in another CommonJS module??
An alternate way to define it would be the way Jquery's typescript definition is defined. You have separate interfaces for static and instance members. Here is a sample complete definition:
interface IExternal {
inheritedMethod():void;
}
interface IRingBuffer extends IExternal {
write():void;
}
// Static functions and constructors
interface IRingBufferStatic{
new():IRingBuffer;
}
declare var RingBuffer:IRingBufferStatic;
declare module "bunyan" {
export var RingBuffer:IRingBufferStatic;
}
// In the second file
import bunyan = require( 'bunyan' );
var rb = new bunyan.RingBuffer();
// you get an error here
rb.badFunc();
Try it online