I cannot import and use the type definitions from @sendgrid/mail
with TS v2.8.1. Very likely that I've just misunderstood, but have tried a few things after reading the index.d.ts
.
Seems the type I would like is MailService & { MailService: MailService; }
, so says tsc
if I try to arbitrarily assert something like:
SendGrid.setApiKey('blahblah')
export default Sendgrid as SomethingElse
Doesn't work:
import SendGrid = require('@sendgrid/mail')
interface Foo {
mail: Sendgrid.MailService // [ts] Cannot find namespace 'Sendgrid'
}
Also doesn't work:
import { MailService } from '@sendgrid/mail'
interface Foo {
mail: MailService // [ts] Cannot find name 'MailService'
}
tsconfig.json:
{
"compilerOptions": {
"baseUrl": "./",
"module": "commonjs",
"outDir": "dist",
"sourceMap": true,
"strict": true,
"target": "es6",
"paths": {
"@/*": ["src/*"]
}
}
}
Mentioned this in #476 - thought it might be related.
@SPARTAN563,
Any ideas?
Hi @killtheliterate,
Can you let me know if this works for you?
import * as SendGrid from "@sendgrid/mail";
SendGrid.setApiKey("blahblah")
interface Foo {
mail: typeof SendGrid.MailService
}
const foo: Foo = {
mail: SendGrid
}
export = foo
It appears to work fine locally for me, the big difference being the use of the typeof
keyword when referencing the MailService
type within your interface.
@SPARTAN563 that does the trick, thank you! Is there a link you could toss me that explains why the typeof
is necessary?
Great!
The reason why the original version ({ mail: SendGrid.MailService }
) doesn't work is that you're attempting to treat a value as a type. The typeof
operator transforms that value into a type which can then be used within the type system to build the constraint you're looking for.
Take the following example:
const X = {
x: String
}
interface Y {
y: X.x
}
Looking at that, you'd probably expect it not to work since you're trying to constrain a type based on the value of a const
object ({ x: String }
). However to accomplish what is implied by that example, you could ask TypeScript to constrain based on the type of the value, in this case:
const X = {
x: String
}
interface Y {
y: typeof X.x // String
}
Exactly the same thing is at play here due to the gymnastics we had to perform to represent the library's interface in TypeScript. Unfortunately libraries that make use of the old NodeJS module.exports = X
export format will continue to encounter problems like this and while we can work around it with virtual namespaces and XConstructor
interfaces, it generally isn't worth it and leads to even more confusion.
I hope that explains what's going on and why, but please feel free to ask if you've got any other questions or if my explanation isn't clear.
@SPARTAN563 thanks so much for the explanation!
Good evening,
My app is on firebase (node.js), and I had the same problem.
I changed the way I imported @sendgrid
I also set up single sender verification on app.sendgrid.com.
Before:
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);
After:
import * as SendGrid from "@sendgrid/mail";
const SENDGRID_API_KEY = functions.config().sendgrid.key
SendGrid.send(msg).then( snapshotMail => {
console.log("Passou D")
console.log("Sucesso")
console.log(snapshotMail[0])
console.log(snapshotMail[1])
}).catch((e)=> console.error(e.message));
@dougadriquei I'm having the same problem, but import * as SendGrid from "@sendgrid/mail";
doesn't work for me and results in TypeError: s.setApiKey is not a function
. So I have to use import SendGrid ...
normally, and when console.log
ging the functions are there as expected.
I'm on CloudFlare workers. It works on Nodejs as expected :confused:
According to SendGrid's docs Single Sender Verification doesn't apply to me.
Turns out import * as
doesn't matter it's just peculiarity of esModuleInterop
being set to true
, once set back to false
and import being import * as
it still doesn't work :confused:
Most helpful comment
Hi @killtheliterate,
Can you let me know if this works for you?
It appears to work fine locally for me, the big difference being the use of the
typeof
keyword when referencing theMailService
type within your interface.