This works fine AFAIK:
(function f() {
console.log(f.name); //logs f
})();
But some of the answers posted here are a lot longer, which makes me think that I might be missing a gotcha (In other words it works in this case, BUT ...) with the above statement?
Here's a slightly different typescript variation:
function f1() {}
function f2(f:Function) {
console.log(f.name);
}
f2(f1);
The Function.name property is only available in ES6/ES2015-compliant engines. So for example if you try to access it without additional configuration in Typescript you will get the error:
[ts] Property 'name' does not exist on type 'Function'.
So for typescript include es2015 in your --lib value to get the property declaration.
{
"compilerOptions": {
...
"lib": ["es2015"], /* Specify library files to be included in the compilation. */
...
}
Related
Summernote is a jQuery plugin, and I don't need type definitions for it. I just want to modify the object, but TS keeps throwing errors. The line bellow still gives me: "Property 'summernote' does not exist on type 'jQueryStatic'." error.
(function ($) {
/* tslint:disable */
delete $.summernote.options.keyMap.pc.TAB;
delete $.summernote.options.keyMap.mac.TAB;
/* tslint:enable */
})(jQuery)
Edit:
Here is my tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"allowJs": true,
"noUnusedParameters": true
},
"include": [
"js/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
As of Typescript 2.6, you can now bypass a compiler error/warning for a specific line:
if (false) {
// #ts-ignore: Unreachable code error
console.log("hello");
}
Note that the official docs "recommend you use [this] very sparingly". It is almost always preferable to cast to any instead as that better expresses intent.
Older answer:
You can use /* tslint:disable-next-line */ to locally disable tslint. However, as this is a compiler error disabling tslint might not help.
You can always temporarily cast $ to any:
delete ($ as any).summernote.options.keyMap.pc.TAB
which will allow you to access whatever properties you want.
#ts-expect-error
TypeScript 3.9 introduces a new magic comment. #ts-expect-error will:
have same functionality as #ts-ignore
trigger an error, if actually no compiler error has been suppressed (= indicates useless flag)
if (false) {
// #ts-expect-error: Let's ignore a compile error like this unreachable code
console.log("hello"); // compiles
}
// If #ts-expect-error didn't suppress anything at all, we now get a nice warning
let flag = true;
// ...
if (flag) {
// #ts-expect-error
// ^~~~~~~~~~~~~~~^ error: "Unused '#ts-expect-error' directive.(2578)"
console.log("hello");
}
Playground
What do TypeScript developers recommend?
#ts-ignore and #ts-expect-error are like a sledgehammer for compile errors. TypeScript developers recommend more fine-grained, narrow-scoped typesystem solutions for most cases:
We added ts-ignore with the intent that it be used for the remaining 5% that can't be suppressed by any existing type system mechanics [...] there should be very very very few ts-ignores in your codebase[.] - microsoft/TypeScript#19139
[...] fundamentally, we believe you shouldn't be using suppressions in TypeScript at all. If it's a type issue, you can cast out of it (that's why any, casting, and shorthand module declarations exist). If it's a syntax issue, everything is awful and we'll be broken anyway, so suppressions won't do anything (suppressions do not affect parse errors). - microsoft/TypeScript#19573
Alternatives for question-case
▶ Use any type
// type assertion for single expression
delete ($ as any).summernote.options.keyMap.pc.TAB;
// new variable assignment for multiple usages
const $$: any = $
delete $$.summernote.options.keyMap.pc.TAB;
delete $$.summernote.options.keyMap.mac.TAB;
▶ Augment JQueryStatic interface
// ./global.d.ts
interface JQueryStatic {
summernote: any;
}
// ./main.ts
delete $.summernote.options.keyMap.pc.TAB; // works
In other cases, shorthand declarations / augmentations are handy utilities to compile modules with no / extendable types. A viable strategy is also to incrementally migrate to TypeScript, keeping not yet migrated code in .js via allowJs and checkJs: false compiler flags.
You can simple use the following just before the line:
// #ts-ignore
I used // #ts-ignore:next-line right before the error.
If you're using eslint to perform your check or fix you can disable a line by adding this on top of the line
// eslint-disable-next-line #typescript-eslint/<RELEVANT_ESLINT_RULE>
I am trying a simple class in typescript using Visual Studio 2015. Somehow, the TypeScript doesn't recognize getElementById! The following is the code I am using which I downloaded from another thread.
class TypeSearch {
searchKey = document.getElementById('search').addEventListener('click', () => this.search());
search() {
alert("i am clicked");
}
}
The error is "Can't resolve symbol getElementById"
Thanks
You are missing the typings (type definition) for DOM.
You need to add the dom lib:
https://www.typescriptlang.org/docs/handbook/compiler-options.html
// tsconfig.json
{
"compilerOptions": {
"lib": [
"dom"
],
...
}
}
Have you successfully transpiled your typescript file into a Javascript file and caught the described error at runtime? If not, i.e. you get transpilation error, just add declare var document: any.
I am using Grunt as my Build Tool and ESLint as my linting tool for an app I am working on. I am also using the Underscore Node package, and have made use of it in my app. Unfortunately, when I run ESLint on my code, it thinks that _ is an undefined variable in the following line:
return _.pluck(objects, nameColumn);
This is the error it is giving me:
78:21 error "_" is not defined no-undef
I would prefer not to disable the no-undef rule for ESLint, and I have tried installing the Underscore plugin, but I am still receiving this error. If anyone else has any ideas for what to try with this, I would be very appreciative!
If there is any further information I can give that would help anyone with helping me get this figured out, just let me know!
The official documentation should give you an idea on how to fix this.
Any reference to an undeclared variable causes a warning, unless the variable is explicitly mentioned in a /*global ...*/ comment, or specified in the globals key in the configuration file.
The easiest fix would be to add
/* global _ */
at the top of your file.
Or better, explicitly specify that the variable is read-only, to disallow overwriting the variable:
/* global _:readonly */
But since you'll have to do that for each new js file, it can get annoying. If you are using underscore often, I'd suggest to add globals to your .eslintrc file, for example:
{
"globals": {
"_": "readonly"
}
}
And save this as .eslintrc in your project root, or optionally in your user home directory. Although some say the latter not recommended, it can sometimes be convenient, but you have to remember that you have it there :)
Explanation of the above rule: "_": "readonly" (used to be "_": false, now deprecated) means that a variable named _ tells eslint that this variable is defined globally and it will not emit any no-undef errors for this variable. As #sebastian pointed out, "readonly" (or false - deprecated) means that the variable can't be overwritten, so the code _ = 'something else' would yield an error no-global-assign. If you were to instead use "_": "writable" (or "_": true - deprecated), this means that the value can be re-assigned and the previously mentioned error will not occur.
But keep in mind that this will only happen if you assign directly to the global variable as I have shown in the example. You can still shadow it and eslint won't say anything. For example, these snippets wouldn't yield the no-global-assign:
const _ = 'haha I broke your _'
or as function argument name, e.g.
function (_) {
console.log(_, 'might not be the _ you were looking for')
}
If you are using jest for testing - in your environment - in eslintrc.json
"env":{
"jest":true
}
I have a typescript file containing a class definition:
if (window.console == null) {
(<any>window).console = {
error: function (a) {
},
log: function (a) {
}
};
}
class SendMessage {
//.....
}
After the compilation to javascript (by VS2015), I get the error on the line with the class definition:
Uncaught SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
I have found that I have to use the strict mode. But why and how can I use it in typescript?
Thanks
It's because it's compiling to ES6 and the browser is requiring that block-scoped declarations be used in strict mode.
You can fix this by using strict mode. To do that add...
"use strict";
...to the top of every file.
However, I think you probably want to change the compilation target from ES6 to ES5. If you are using tsconfig.json, change "target": "es6" to "target": "es5". Doing that will...compile to ES5...and so block-scoped declarations will be changed appropriately so "use strict"; will not be required. Additionally, more browsers will support your code. Right now runtime ES6 support is still not widespread.
Note that if you are not using tsconfig.json, you might have to change the target in the project properties' typescript build tab as shown here:
The first file that I am passing to uglifyjs declares some namespaces like
window.MyNamespace = {}
when uglifyjs sees this line it complains that window is not defined.
Is there a way to have uglifyjs ignore undefined symbols? I have tried using the --no-dead-code option
You can wrap your global code in a function:
(function(window) {
window.whatever = something;
// ...
})(this);
You can also do this:
(function(window) {
"use strict";
// ...
})(this);
which is probably a good idea anyway. You'll get warnings/errors from stray undefined variables even without uglify.