Accessing inline type in the constructor - node.js

I have this:
export class QueueEntity<T> implements HasInternalQueue<T> {
opts: { // <--- inline type here
foo: boolean
}
constructor(v: typeof this.opts) { // this doesn't quite work
this.opts = v
}
}
is there a way to reference the inline type or is this not possible?

Since there is no way to define a type inside the class directly (An open issue in the TS repo). I think you can use the class name to reference this:
export class QueueEntity<T> {
opts: { // <--- inline type here
foo: boolean
}
constructor(v: QueueEntity<T>['opts']) { // <-- should work now
this.opts = v
}
}
const obj = new QueueEntity({ foo : false });
const obj2 = new QueueEntity({ foo2 : false });
const obj3 = new QueueEntity();
Playground

Related

NodeJS: Can a static method call the constructor of the same class?

I've got a question: If I have a constructor in a class:
module.exports = class ClassA{
constructor(stuffA, stuffB) {
this.stuffA = stuffA;
this.stuffB = stuffB;
}
NonStaticMethod() {
console.log(this);
}
static StaticMethod(stuffA, stuffB) {
const element = new ClassA(stuffA, stuffB);
console.log(element)
element.NonStaticMethod();
});
}
};
So, the NonStaticMethod prints other information for the object than the StaticMethod. So two questions:
Can I call the constructor from a static method from the same class?
What should be the correct way of calling the non-static method from the static method?
The following code prints "true", so in NonStaticMethod this.stuffA rely correctly on value defined in constructor:
class ClassA{
constructor(stuffA, stuffB) {
this.stuffA = stuffA;
this.stuffB = stuffB;
}
NonStaticMethod() {
console.log(this.stuffA === "a");
}
static StaticMethod(stuffA, stuffB) {
const element = new ClassA(stuffA, stuffB);
element.NonStaticMethod();
};
}
ClassA.StaticMethod("a","b")

this is undefined in extended class

I have these 3 files:
bar.js
class Bar {
test(p) {
console.log(p);
}
}
module.exports = Bar;
baz.js
const Bar = require('./bar');
class Baz extends Bar {
test2(p) {
this.test(p);
}
}
module.exports = Baz;
foo.js
const Baz = require('./baz');
const { test2 } = new Baz();
test2('test');
When I passed 'test' to new Baz.test2(), I expected it to pass it to it's superclass (this.test(p)) where it should log 'test'. However, it threw the error:
this.test(p);
^
TypeError: Cannot read property 'test' of undefined
What am I doing wrong? Why is this undefined, I thought it should reference the class itself?
test2 is used apart from it's original context (Bar instance) and should be bound to proper this.
It's impossible to say from the name if it's expected to be a callback by design. In case it is, it can be bound in constructor:
class Bar {
constructor () {
this.test = this.test.bind(this);
}
...
}
Otherwise it can be bound in-place:
const test2 = new Baz().test2.bind(this);
test2('test');
Or just not be used separately from the context:
const baz = new Baz()
baz.test2('test');

Is it possible to extend a class method in JavaScript?

Suppose I have a class A with the following method:
foo(x, options) {
const limit = options && options.limit ? options.limit : undefined;
const select = options && options.select ? options.select : {};
const paginate = options && options.paginate ? options.paginate : {};
const sort = options && options.sort ? options.sort : {};
const count = options && options.count;
const args = deepMerge({ x }, paginate);
return count ? this.model.find(args).count()
: this.model.find(args).limit(limit).select(select).sort(sort);
}
Then I create a class B that extends A. There I have a method bar that is almost identical to method foo.
Is it possible to extend method bar to have limit,select,paginate,sort and count? I don't want to override foo method in B class, so I need it to have a distinct name
You can use the this.foo() if you haven't overwritten the foo() method on B, else, you can use the super keyword which refers to the parent class instance super.foo() and it works in both cases (overwritten or not).
class B extends A {
bar(){
super.foo();
}
}
Disclaimer: I'm assuming that: by class, you mean ES6 classes not ES5 prior prototypes.
Working example:
class A {
foo() {
return 'value of A';
}
}
class B extends A {
// case you override the method
// super.foo() still points to the
// original A.foo() but you don't
// have to do this, it's just an
// example
foo() {
return 'value of B';
}
bar() {
const valueOfA = super.foo();
return valueOfA;
}
}
const b = new B();
console.log(b.bar())

TypeScript ignore expression `if (object instanceof SomeClass)` inside `for(){}`? Or not?

I have code (see comments):
class ClassA
{
propA: any;
}
class ClassB
{
propB: any;
}
function fn( arr: (ClassA | ClassB)[] )
{
for( let element of arr )
{
if( element instanceof ClassA )
{
element.propA = true; // Work as expected
() =>
{
element.propA; // Unexpected error
}
}
}
}
Message of unexpectedly error:
Property 'propA' does not exist on type 'ClassA | ClassB'.
Property 'propA' does not exist on type 'ClassB'.
When I remove the loop for(){}. Works as expected:
class ClassA
{
propA: any;
}
class ClassB
{
propB: any;
}
function fn( element: ClassA | ClassB )
{
if( element instanceof ClassA )
{
element.propA = true; // Work as expected
() =>
{
element.propA; // Work as expected
}
}
}
It's a bug?
Resolved by aluanhaddad - contributor TypeScript:
Your inner function is closing over a mutable binding that is scoped outside the if block and is thus not always going to be an instance of ClassA.
To make this work, use a const binding:
function fn(arr: (ClassA | ClassB)[]) {
for(const element of arr) {

How to register global TypeScript Enum in Node.js

I want to make my TypeScript Enums global so I don't need to import them across my application.
What I have so far:
read-state.enum.ts
export enum ReadState {
Unread = 4000,
Read = 4001
}
enums.ts
import { ReadState } from './read-state.enum';
const enums = {
ReadState
}
global['Enums'] = enums;
declare var Enums: typeof enums;
Then in index.ts
import './enums'; // do this once to initialize enums
var _enums = Enums; // [ts] Cannot find name 'Enums'.
While at runtime this might work, I'm not able to reference the enums through the declare var Enums: typeof enums; because the file is a module.
How can I reference this type definition without importing the module while keeping future enum definitions in separate files?
UPDATE: I also need to set the return type of a function to be the ReadState enum.
Based on the current selected answer I have this:
import { ReadState } from './read-state.enum';
const enums = {
ReadState: ReadState
}
declare global {
const Enums: typeof enums;
}
In another file I would like to set the return type on these functions but TypeScript is unhappy:
function getState1(): Enums.ReadState {
return Enums.ReadState.Unread;
}
function getState2(): typeof Enums.ReadState {
return Enums.ReadState.Read;
}
Use a declare global block:
declare global {
const Enums: typeof enums;
}

Resources