TypeScript + Express: Property 'rawBody' does not exist on type 'IncomingMessage' - node.js

In my src/app.ts, I have:
import express from 'express';
import bodyParser from 'body-parser';
const app = express()
app.use(bodyParser.json({ verify: (req, res, buf) => req.rawBody = buf }))
But I get the error Property 'rawBody' does not exist on type 'IncomingMessage' on:
app.use(bodyParser.json({ verify: (req, res, buf) => req.rawBody = buf }))
I have a typings/express.d.ts, in which I have:
declare namespace Express {
export interface Request {
rawBody: any;
}
}
and my tsconfig.json is:
{
"compilerOptions": {
"outDir": "./built",
"allowJs": true,
"target": "es6",
"esModuleInterop": true,
"sourceMap": true,
"moduleResolution": "node"
},
"include": [
"./src/**/*"
],
"files": [
"typings/*"
]
}
So what am I doing wrong?

There are two issues here:
1. tsconfig.json
The files option in tsconfig.json doesn't support wildcards like typings/*, only explicit filenames.
You can either specify the full path:
"files": [
"typings/express.d.ts"
]
Or add the wildcard path to include:
"include": [
"./src/**/*",
"typings/*"
]
2. Wrong Type
The error message mentions the type IncomingMessage, however you are augmenting the Request interface instead. Take a look at the type definitions for body-parser (parts omitted):
import * as http from 'http';
// ...
interface Options {
inflate?: boolean;
limit?: number | string;
type?: string | string[] | ((req: http.IncomingMessage) => any);
verify?(req: http.IncomingMessage, res: http.ServerResponse, buf: Buffer, encoding: string): void;
}
The first argument of verify has the type http.IncomingMessage from the 'http' module that's included with Node.js.
To augment the correct type, you'll want to change your .d.ts file to this:
declare module 'http' {
interface IncomingMessage {
rawBody: any;
}
}

Related

Sinon stub failed when upgrade ts-node to v10

Everything is ok when my ts-node version is 8.x ~ 9.x , but sinon stub failed when I upgraded ts-node to 10.x
The code likes below:
// file: ./lambda.ts
export const getAWSLambda = () => new AWS.Lambda({ region: AWS_DEFAULT_REGION });
export class AWSLambda {
private readonly lambda: AWS.Lambda;
constructor() {
this.lambda = getAWSLambda();
}
async invoke(params: ServerlessParams): Promise<ServerlessResponse> {
const response = await this.lambda.invoke({
// ...
}).promise();
return {};
}
}
// file: unit.test.ts
import sinon from 'sinon';
import * as lambda from './lambda';
describe('Lambda Unit Test', () => {
let lambdaService: lambda.AWSLambda;
let sandbox: sinon.SinonSandbox;
let getAWSLambdaStub: sinon.SinonStub;
let invokeStub: sinon.SinonStub;
before(() => {
sandbox = sinon.createSandbox();
});
beforeEach(() => {
invokeStub = sandbox.stub();
getAWSLambdaStub = sandbox.stub(lambda, 'getAWSLambda');
getAWSLambdaStub.returns({
invoke: () => ({
promise: invokeStub,
}),
});
lambdaService = new lambda.AWSLambda();
});
it('shound succeed to invoke', async () => {
invokeStub.resolves({
StatusCode: 200,
});
// -----------
// called real function, stub failed.
const res = await lambdaService.invoke();
expect(getAWSLambdaStub).to.be.calledOnce;
expect(invokeStub).to.be.calledOnce;
});
});
The stub failed, the real function was called.
sinon: 11.1.2
ts-node: 10.2.1
typescript: 3.9.7
node: 14.17.3
tsconfig.json:
{
"compilerOptions": {
"preserveConstEnums": true,
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strict": true,
"moduleResolution": "node",
"sourceMap": false,
"outDir": "dist/src",
"allowJs": true,
"checkJs": true,
"noUnusedLocals": true,
"skipLibCheck": true
},
"ts-node": {
"transpileOnly": true,
"transpiler": "ts-node/transpilers/swc-experimental"
}
}
Everything is ok when my ts-node version is 8.x ~ 9.x , but sinon stub failed when ts-node is v10. Is there any change in the import of module for ts-node's swc ?
Add swc integration and new --transpiler option to use third-party transpilers for a massive speed boost on large codebases
I guess here is the cause of the problem, and I want to use ts-node v10, but I don't known how to fix the problems.

Importing Static Functions Typescript

I am trying to import a static class function into my main.js file but using the function after compiling with tsc I get:
TypeError: Cannot read property 'router' of undefined
at Object. (path/to/main.js:36:27)>
I have tried to assign it a type with no luck as well as using different methods of importing again with no luck...
I feel as if the answer is simple but cant seem to locate it in the TS docs and I'm just banging my head at this point.
Here is the class I am trying to export.
Session.ts
export class Session {
//Class Members
constructor() {
//Big constructor lots of this. =
};
//Creating the functions needed
logOut() {
delete Session.ssnsById[this.id];
delete Session.ssnsByCookie[this.authToken];
};
static router = function (req: Request, res: Response, next: Function) {
var cookie = req.cookies[Session.cookieName];
var session = cookie && Session.ssnsByCookie[cookie];
if (session) {
// If the session was last used more than |duration| mS ago..
if (session.lastUsed < new Date().getTime() - Session.duration)
session.logOut();
else {
req.session = session;
}
}
next();
};
}
module.exports = Session;
Importing into my main.ts
import { Session } from "./Session";
// Set up Session on req if available
app.use(Session.router); //<--
After running tsc we get built/main.js
const Session_1 = require("./Session");
// Set up Session on req if available
app.use(Session_1.Session.router); //<-This line throws the error.
Lastly here is my tsconfig.json used to compile
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"noImplicitAny": true,
"noImplicitThis": true,
"moduleResolution": "node",
"sourceMap": false,
"baseUrl": ".",
"outDir": "built",
"paths": {
"*": [
"node_modules/*"
]
}
},
"include": [
"Src/**/*"
]
}
1: Please remove module.exports = Session;
2: Add a new file name 'custom.d.ts' in the root directory and add the following:
import { Session } from "./Session";
declare module 'express-serve-static-core' {
interface Request {
router?: typeof Session['router'],
}
}
3: Do this in the file where you imported Session class.
import {Request, Response, NextFunction} from 'express';
import { Session } from "./Session";
// Set up Session on req if available
app.use((req: Request, res: Response, next: NextFunction) => {
req.router = Session.router;
next();
});
You will have your router on the req :)
Removing module.exports = Session; Cleared the problem for me!

typescript error running navalia example

I am trying to run this example from https://github.com/joelgriffith/navalia but for the light of me, I couldn't get it to work without error:
navaliatest.ts
/// <reference path="typings.d.ts" />
import { Chrome } from 'navalia';
const chrome = new Chrome();
async function buyItOnAmazon() {
const url = await chrome.goto('https://amazon.com');
const typed = await chrome.type('input', 'Kindle');
const clicked = await chrome.click('.nav-search-submit input');
chrome.done();
console.log(url, typed, clicked); // 'https://www.amazon.com/', true, true
}
buyItOnAmazon();
tsconfig.json
{
"files": [
"navaliatest.ts"
],
"compilerOptions": {
"noImplicitAny": false,
"target": "es6",
"moduleResolution": "node",
"paths": {
"*" : ["/usr/local/lib/node_modules/*"]
}
}
}
typings.d.ts
/// <reference path="/usr/local/lib/node_modules/navalia/build/Chrome.d.ts" />
declare module 'navalia' {
var Chrome: any;
export = Chrome;
}
Below are the versions:
MacBook-Pro:testcasperjs myusername$ node --version
v6.11.2MacBook-Pro:testcasperjs myusername$ npm --version
3.10.10
MacBook-Pro:testcasperjs myusername$ tsc --version
Version 2.4.2
This is the error I got although I do get .js file output:
MacBook-Pro:testcasperjs myusername$ tsc navaliatest.ts
../../../usr/local/lib/node_modules/navalia/node_modules/chrome-launcher/chrome-finder.ts(203,16): error TS2339: Property 'from' does not exist on type 'ArrayConstructor'.
../../../usr/local/lib/node_modules/navalia/node_modules/chrome-launcher/chrome-launcher.ts(99,15): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
navaliatest.ts(3,10): error TS2305: Module ''navalia'' has no exported member 'Chrome'.
I am sure there is a stupid mistake somewhere but please could someone help me and take a look? Thanks.
You don't need to redeclare navalia. It has already been done for you at node_modules/navalia/build/index.d.ts given that moduleResolution is set to Node
You'll need to set module to commonjs so that you can run it in node
tsconfig.json
{
"files": [
"navaliatest.ts"
],
"compilerOptions": {
"noImplicitAny": false,
"target": "es6",
"module": "commonjs",
"moduleResolution": "Node"
}
}
navaliatest.ts (No change)
import { Chrome } from 'navalia';
const chrome = new Chrome();
async function buyItOnAmazon() {
const url = await chrome.goto('https://amazon.com');
const typed = await chrome.type('input', 'Kindle');
const clicked = await chrome.click('.nav-search-submit input');
chrome.done();
console.log(url, typed, clicked); // 'https://www.amazon.com/', true, true
}
buyItOnAmazon();
It'll create navaliatest.js with no errors, which can be run in node.

Cannot invoke an expression whose type lacks a call signature when using node-fetch

I'm trying to get node-fetch to work in my typescript project:
import * as fetch from 'node-fetch';
import * as assert from 'assert';
export class DatabaseConfigurator {
private url: string;
getNode (): Promise<string> {
return fetch(`${this.url}/_membership`).then((response: fetch.Response) => {
return response.json();
}).then((res: any) => {
assert.equal(res.all_nodes.length, 1);
return res.all_nodes[0];
});
}
}
And I get:
Cannot invoke an expression whose type lacks a call signature. Type 'typeof "/home/vinz243/compactd/node_modules/#types/node-fetch/index"' has no compatible call signatures.
When the definition i installed seems ok (node_modules/#types/node-fetch/index.d.ts):
...
export default function fetch(url: string | Request, init?: RequestInit): Promise<Response>;
My tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"outDir": "./dist/",
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"allowJs": true
},
"include": [
"./src/**/*"
]
}
You've imported the entire module rather than the default export, the fetch function. You're trying to call the entire module as a function which doesn't work.
Instead of
import * as fetch from 'node-fetch';
try
import fetch from 'node-fetch';

Typescript - tsc compiler breaks my code

I wrote this code in Typescript
import redis from 'redis';
import Promise from 'bluebird';
const DEFAULT_REDIS_TTL = 7200; // 2 hours
export default class Redis {
readonly client : any;
ttl : number = DEFAULT_REDIS_TTL;
constructor(uri? : string, ttl : number = DEFAULT_REDIS_TTL) {
this.client = redis.createClient(uri);
}
...
}
export { Redis };
the compiler gives me this
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var redis_1 = require("redis");
var bluebird_1 = require("bluebird");
var DEFAULT_REDIS_TTL = 7200; // 2 hours
var Redis = (function () {
function Redis(uri, ttl) {
if (ttl === void 0) { ttl = DEFAULT_REDIS_TTL; }
this.ttl = DEFAULT_REDIS_TTL;
this.client = redis_1.default.createClient(uri);
this.client.on('error', function (error) {
console.error(error);
});
...
exports.Redis = Redis;
exports.default = Redis
I don't know why 'redis.createClient(uri);just becomeredis_1.default.createClient(uri);`
I get the following error when trying to run my code in node
build/Lib/Cache/Redis.js:11
this.client = redis_1.default.createClient(uri);
^
TypeError: Cannot read property 'createClient' of undefined
my tsconfig looks like this
{
"compilerOptions": {
"module": "mymodule",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"module": "commonjs",
"outDir": "build"
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
I run the compiler in main directory
tsc
I'm using node 6.7.2
Change your import to:
import * as redis from 'redis';
I don't think the typings for redis has a default export. Make sure you have the latest typings.
If you have the latest typings, import redis from 'redis'; should throw a compile time error.

Resources