This expression is not callable. Type 'string' has no call signatures - node.js

I'm trying to create a template file from an object where the key can be either a string or a function that returns a string:
export const createDynamicTemplate = (
templateParams: CreateDynamicTemplateParams
) => {
const { template, projectPath = '', param = '' } = templateParams
const updatedTemplateArr = Object.keys(template).map((key: string) => {
return {
[key]: {
filePath: `${projectPath}/${key}`,
template: typeof template[key] === 'function' ?
template[key](param) : template[key],
},
}
})
const updatedTemplate = Object.assign({}, ...updatedTemplateArr)
return updatedTemplate
}
My interfaces are:
export interface TemplateObject {
[key: string]: string
}
export interface FunctionalTemplateObject {
[key: string]: (param: string) => void
}
export interface CreateDynamicTemplateParams {
template: FunctionalTemplateObject | TemplateObject
projectPath: string
param: string
}
It keeps throwing this error in createDynamicTemplate though:
This expression is not callable.
Not all constituents of type 'string | ((param: string) => void)' are callable.
Type 'string' has no call signatures.
What am I doing wrong here?

Checking the type of a child property of a variable which references an object will not narrow the type of the variable-object. You can save the value at the key in a separate variable first, then check that value to narrow its type:
const updatedTemplateArr = Object.keys(template).map((key: string) => {
const item = template[key];
if (typeof item === 'function') {
return {
[key]: {
filePath: `${projectPath}/${key}`,
template: item(param),
},
}
}
})
Or, even better, use Object.entries to get the key and value at once. (Also note that there's no need to note the type of the .map parameters - TS can infer it automatically just fine)
const updatedTemplateArr = Object.entries(template).map(([key, value]) => {
if (typeof value === 'function') {
return {
[key]: {
filePath: `${projectPath}/${key}`,
template: value(param),
},
}
}
})

Related

Error: ORA-01008: not all variables bound

I have this error for a few hours and I can't identify the problem. Error: ORA-01008: not all variables bound.
Controller
async bipagem(req: Request, res: Response) {
try {
let credentials = super.openToken(req)
let { p_fil_filial, p_set_cdgo, p_mini_fab, p_codigo_barra } = req.query
let info = await this.rep.bipagem(
p_fil_filial as string,
p_set_cdgo as string,
p_mini_fab as string,
p_codigo_barra as string,
credentials as string
)
res.json(info)
} catch (error) {
catchErr(res, error)
}
}
}
Repository
public async bipagem(
p_fil_filial: string,
p_set_cdgo: string,
p_mini_fab: string,
p_codigo_barra: string,
userPool: string
) {
let conn
try {
conn = await connection(userPool)
const ret = await conn.execute(
`DECLARE
c_result SYS_REFCURSOR;
BEGIN
-- Call the function
:result := brio.pck_fab0024.bipagem(p_fil_filial => :p_fil_filial,
p_set_cdgo => :p_set_cdgo,
p_mini_fab => :p_mini_fab,
p_codigo_barra => :p_codigo_barra,
p_msg => :p_msg);
DBMS_SQL.RETURN_RESULT(c_result);
END;`,
{
p_fil_filial,
p_set_cdgo,
p_mini_fab,
p_codigo_barra,
p_msg: { type: oracledb.STRING, dir: oracledb.BIND_OUT }
}
)
return { ...(ret.outBinds as object), conteudo: ret.implicitResults[0] }
} catch (e) {
console.log('Erro na fab0024: ', e.message)
return {
p_fil_filial,
p_set_cdgo,
p_codigo_barra,
p_msg: '',
conteudo: []
}
} finally {
if (conn && typeof conn !== 'string') conn.close()
}
}
}
I tried to include the p_msg parameter and got this return error TS2339: Property 'bipagem' does not exist on type 'unknown'.
Your PL/SQL block has six bind parameters but you are passing only five values. Hence it is not a surprise that you get an error saying that one of the local variables isn't bound.
I think you have missed the fact that :result in the line below is also a bind parameter:
:result := brio.pck_fab0024.bipagem(p_fil_filial => :p_fil_filial,
I suspect you meant to assign the result to the local variable c_result (to which you don't currently assign any value) instead of an extra bind parameter:
c_result := brio.pck_fab0024.bipagem(p_fil_filial => :p_fil_filial,

How can I convert from a firebase document to a custom class in Node JS

In node.js I'm getting the error below. Any ideas why?
Conversion of type 'Promise' to type 'Member[]' may be a mistake
because neither type sufficiently overlaps with the other. If this was
intentional, convert the expression to 'unknown' first. Type
'Promise' is missing the following properties from type
'Member[]': length, pop, push, concat, and 26 more.
export async function getFamilyMembers(tenantId: string, familyCode: string): Promise<Member[]> {
return db.collection(`tenants/${tenantId}/members`)
.where('familyCode', '==', familyCode)
.get()
.then(snaps => {
snaps.docs.forEach(doc => {
return { id: doc.id, ...doc.data()}
});
}) as Member[];
}
EDIT:
If I remove the types and change it to
export async function getFamilyMembers(tenantId: string, familyCode: string) {
return db.collection(`tenants/${tenantId}/members`)
.where('familyCode', '==', familyCode)
.get()
.then(snaps => {
snaps.docs.forEach(doc => {
return { id: doc.id, ...doc.data()}
});
});
}
I just have to deal with the problem later.
I get the error
Property 'length' does not exist on type 'void'.
const familyMembers: Member[] | void = await getFamilyMembers(tenantId, familyCode);
if (familyMembers === null) {
isVerified = false;
verificationFailMessage = `Sorry we can't find this code. Please check it is correct.`;
} else if (familyMembers.length === 0) {
I needed to add Promise in front of Member.
export async function getFamilyMembers(tenantId: string, familyCode: string): Promise<Member[]> {
return db.collection(`tenants/${tenantId}/members`)
.where('familyCode', '==', familyCode)
.get()
.then(snaps => {
snaps.docs.forEach(doc => {
return { id: doc.id, ...doc.data()}
});
}) as Promise<Member[]>;
}

this is unset inside a function method when decorators are applied

I'm writing decorators for the following class method:
export default class API {
...
public async request(url_stub: string, options: any = {}): Promise<any> {
console.log(this)
const url = this.join_url(url_stub);
...
}
}
The functions run as expected when no decorators are applied, but when I apply one of the following decorators:
export function log_func(_target: any,
name: string,
descriptor: PropertyDescriptor): PropertyDescriptor {
const original_function = descriptor.value;
descriptor.value = (... args: any[]) => {
const parameters = args.map((a) => JSON.stringify(a)).join();
const result = original_function.apply(this, args);
const result_str = JSON.stringify(result);
console.log(`Call: ${name}(${parameters}) => ${result_str}`);
return result;
}
return descriptor;
}
export function uri_encode(parameter_index?: number) {
return (_target: any,
name: string,
descriptor: PropertyDescriptor): PropertyDescriptor => {
const original_function = descriptor.value;
descriptor.value = (... args: any[]) => {
args = args.map((arg, index) => {
if (parameter_index === undefined || index === parameter_index) {
arg = encodeURI(arg);
}
return arg;
});
const result = original_function.apply(this, args);
return result;
}
return descriptor;
}
}
as such:
#uri_encode(0)
#log_func
public async request(url_stub: string, options: any = {}): Promise<any> {
this inside the class method is now undefined. I'm guessing this is because the method is technically being called from outside the context of the class.
Is there a flaw in my design, or is this what I should expect? If so is there a way for me to retain the context while still using decorators?
The problem was in my decorator. Apparently modifying the original descriptor value with a () => {} function was the problem. Changing it to function () {} made it work.
God knows why.

GraphQL Resolver returns error "Cannot read forEach of Undefined"

I have a graphql endpoint that I'm running a query against, and I'm building my resolver that is massaging the data before returning to the client. My query is this:
query getTransactions($transID: String!, $confidence: Float) {
transactions(parentID: $transID, confidence: $confidence) {
id
childrens {
id
name
email
phone
age
connectionInfo {
type
confidence
}
}
name
email
phone
age
}
}
and my resolver is currently looking like this:
const getTransactions = (args: any): any => {
const { parentID, confidence } = args;
const trxs = transactions.filter(t => {
return t.id === parentID;
});
let finalChildrens: any[] = [];
trxs.forEach(t => {
finalChildrens.concat(filteredChildren(t));
});
trxs.concat(finalChildrens);
return trxs;
};
const filteredChildren = (t: any): any[] => {
log.debug({ typeCheck: typeof t.childrens, children: t.childrens });
let outputChildren: any[] = [];
if (typeof t.childrens !== undefined) {
t.childrens.forEach((c1: any) => {
if (typeof c1.childrens !== undefined) {
outputChildren.concat(filteredChildren(c1));
outputChildren.push(c1);
} else {
outputChildren.push(c1);
}
});
return outputChildren;
} else {
return ['no child'] as any[];
}
};
The issue I'm facing is that I'm continually getting this error either in the client or graphiql is this:
"Cannot read property 'forEach' of undefined"
I want to say that it has to do with either the forEach in filteredChildren or inside the resolver itself. I'm going through these "gymnastics" in order to get a flat array that is retrieved recursively from the underlying data. How would someone check the array to see if it's filled or not? (or in this case, if the array exists at all?)
The condition typeof t.childrens !== undefined is always true. You should either use typeof t.childrens !== "undefined" or t.childrens !== undefined.

Require Example of Material AutoComplete with http get request

I am following the Angular Material AutoComplete example as in the Material documents.
It works fine, when using the options[] value as per the document. It is just that I am not able to get it to work when I get the data from api.
If I do not use the filter options, then the list of books are displayed. It is just that when filters are used it has issues.
The this.filterOptions complains
Type 'Observable' is not assignable to type
'Observable'. Type 'Book[]' is not assignable to type
'string[]'.
Type 'Book' is not assignable to type 'string'.
Why did it not complain when options[] was used.
export class AutocompleteComponent implements OnInit {
myControl = new FormControl();
//Works with these values
options = [
'One',
'Two',
'Three'
];
books: Book[] = [];
filteredOptions: Observable<string[]>
constructor(private bookService: BookService) {
this.bookService.getBooks()
.subscribe(
data => {
this.books = data;
},
(err: HttpErrorResponse) => {
console.log(err.statusText);
}
);
}
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.startWith('')
.map(val => {
return this.filter(val)
})
}
filter(val: string): Book[] {
return this.books.filter(option =>
option.toLowerCase().indexOf(val.toLowerCase()) === 0);
}
}

Resources