I have some code that handles a drop event and checks if I have to deal with dropped files:
public handleDrop(evt: DropEvent): boolean {
var isUpload: boolean; = false;
var dt: DataTransfer = evt.DataTransfer;
dt.types.forEach((type)=>{
// dt.types is of type DOMStringList
if(type === "File"){
isUpload = true;
}
})
return isUpload;
}
It works just as it is supposed to be, but the TS-compiler gives me following error message:
(117,16): error TS2339: Property 'forEach' does not exist on type 'DOMStringList'.
First of all, DataTransfer.types will always be an array, so in my understanding I should have access to its array methods.
I tried to create a workaround for my problem, by merging a custom DOMStringList Interface to the one defined in my lib.d.ts:
declare interface DOMStringList {
forEach(cb: Function): any;
}
IntelliJ recognizes the interface and does not show me an error for dt.types.forEach anymore.
However my ts-compiler still throws an error and does not seem to recognize my merged interface.
What is the proper way to tell my ts-compiler that I should be able to use array functions on an DOMStringList?
The problem occurs for other generic types like FileList as well.
EDIT:
ts.config.ts:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"noEmitOnError": false,
"noImplicitAny": false,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
"files": [
"app/typings/app.typings.ts",
"typings/tsd.d.ts"
]
}
Related
I'm building quarkus native and using Stripe sdk as external library.
In order to support Stripe sdk it I needed to create reflection-config.json file and set in the application.properties quarkus.native.additional-build-args=-H:ReflectionConfigurationFiles=reflection-config.json
The reflection-config.json looks like so:
{
"name": "com.stripe.model.Customer",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.Customer$InvoiceSettings",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.StripeError",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.PaymentIntent",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.PaymentMethod",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
}....
and so on.
It contains too many classes.
My question is if there is a way to set the whole package instead of tons of classes?
For example:
{
"name": "com.stripe.model.*",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
}
Didn't find any mention for it.
See update below.
I'm having the exact same use case to programmatically add all classes of a package for reflection without writing an extension.
My goal is to add jOOQ generated DB classes for reflection so I can use them in a native compiled Quarkus GraalVM image with RESTEasy Reactive Jackson.
As there are a lot of these classes I don't really want to manually populate the reflection-config.json or the targets with a #RegisterForReflection annotation on a empty class.
I'm using Quarkus 2.7.0.Final (not io.quarkus.platform as it is not released yet) with Gradle 7.3.3 and tried the following, which unfortunately does not work.
But I guess this only works when building extensions 🤔
package com.example.restapi.graal;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.IndexView;
public class JooqReflectionProcessor {
private static final String JOOQ_DB_REFLECT_CLASSES = "com\\.example\\.restapi\\.db\\..+\\.tables\\.(pojos|records)\\..+";
#BuildStep
public void build(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, CombinedIndexBuildItem indexBuildItem) {
IndexView index = indexBuildItem.getIndex();
for (ClassInfo clazz : index.getKnownClasses()) {
if (clazz.name().toString().matches(JOOQ_DB_REFLECT_CLASSES)) {
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, clazz.name().toString()));
}
}
}
}
Update:
It ain't pretty but I ended up writing a Gradle task which automatically creates the desired jOOQ reflection class with the #RegisterForReflection(targets = {...}) annotation:
task writeJooqReflectionClass {
DefaultSourceDirectorySet sourceSet = project.sourceSets.findByName('main').java
File jooqSrcDir = sourceSet.srcDirs
.stream()
.filter { it.path.replace('\\', '/').matches('.+src/generated/jooq/main') }
.findFirst()
.get()
ArrayList<String> classesForReflection = sourceSet
.filter {
it.path.contains(jooqSrcDir.path) &&
it.path.replace('\\', '/').matches('.+tables/(pojos|records)/.+') &&
it.path.endsWith('.java')
}
.collect { it.path.replaceAll('[\\\\|/]', '.').substring(jooqSrcDir.path.length() + 1).replace('.java', '.class') }
Collections.sort(classesForReflection)
File file = new File("${jooqSrcDir.path}/com/example/restapi/db", "JooqReflectionConfig.java")
file.getParentFile().mkdirs()
file.text = """\
package com.example.restapi.db;
import io.quarkus.runtime.annotations.RegisterForReflection;
#RegisterForReflection(targets = {
${String.join(',\n ', classesForReflection)}
})
public class JooqReflectionConfig {
}
""".stripIndent()
}
compileJava.dependsOn(writeJooqReflectionClass)
For example produces Class com.example.restapi.db.JooqReflectionConfig with content:
package com.example.restapi.db;
import io.quarkus.runtime.annotations.RegisterForReflection;
#RegisterForReflection(targets = {
com.example.restapi.db.master.tables.pojos.TableA.class,
com.example.restapi.db.master.tables.pojos.TableB.class,
com.example.restapi.db.master.tables.records.TableA.class,
com.example.restapi.db.master.tables.records.TableB.class,
com.example.restapi.db.mdc.tables.pojos.TableC.class,
com.example.restapi.db.mdc.tables.pojos.TableD.class,
com.example.restapi.db.mdc.tables.records.TableC.class,
com.example.restapi.db.mdc.tables.records.TableD.class
})
public class JooqReflectionConfig {
}
You can do that with a Quarkus extension, get classes from the index and produce a ReflectiveClassBuildItem for all classes matching the package.
It's not that hard but requires a bit of work.
A less verbose alternative to what you're doing is to use #RegisterForReflection(targets = { ... }).
That's the only alternatives right now.
The cleanest solution seems to be writing a Quarkus extension.
Or, if you don't want to list RegisterForReflection targets manually, another possibility is to have reflection-config.json generated externally (probably using annotation processor? or maven/gradle task).
Suppose the following component class with a public method get_ids() that returns an array of literal values (here: number[]):
class Component {
private _ids: number[];
public get_ids() {
return this._ids;
}
}
The following code works fine as long as the method returns anything else than an array:
const componentSymbol: ts.Symbol = checker.getSymbolAtLocation( componentNode.name ) // componentNode is the AST node of the component class
const componentType: ts.Type = checker.getDeclaredTypeOfSymbol( componentSymbol );
const property: ts.Symbol = componentType.getProperties[1]; // 2nd property represents the method 'get_ids()'
const methodDeclaration = property.getDeclarations()[0] as ts.MethodDeclaration;
const signature = checker.getSignatureFromDeclaration( methodDeclaration );
const returnType = checker.getReturnTypeOfSignature( signature );
However, since get_ids() returns an array, returnType equals:
{
flags: 1,
id: 4,
intrinsicName: "unknown"
}
And there is basically no information that this should be an array of numbers.
Also, the return value of checker.typeToString(checker.getTypeAtLocation(methodDeclaration)) is () => any. I would expect it to be () => number[].
What am I doing wrong here?
I have experimented a bit with the compiler options I have read in from the tsconfig.json file. Turns out that the lib option causes the problem. When commented out, I'm getting the expected result (() => number).
const compilerOptions = {
allowJs: false,
checkJs: false,
diagnostics: false,
inlineSourceMap: true,
inlineSources: true,
jsx: ts.JsxEmit.React,
// lib: [
// // "es5",
// // "dom",
// // "scripthost",
// // "es2015.iterable"
// ],
module: ts.ModuleKind.AMD,
noEmitHelpers: true,
strictNullChecks: false,
tripInternal: true,
target: ts.ScriptTarget.ES5,
downlevelIteration: true,
baseUrl: "./",
pretty: true,
experimentalDecorators: true
};
I'm trying to validate a constructor parameter when creating an instance of a class.
The parameter should be an object containing exactly all the properties (of adequate type) as defined in the class.
If this is not the case, I'd like TypeScript to lint the mismatch.
class User {
username: string;
// more properties
constructor(data:object) {
// Check if data Obejct exactly all the class properties and they are of the right type;
// Set instance properties
}
};
// Desired Output
new User(); // "data parameter missing";
new User(45); // "data parameter is not of type object";
new User(); // "username Poperty missing!";
new User({username:"Michael"}); // Valid;
new User({username:43}); // "username is not of type string";
new User({username:"Michael", favoriteFood: "Pizza"}); // "favoriteFood is not a valid property";
tsconfig.json
{
"compilerOptions": {
"target": "es2016",
"module": "es2015",
"lib": [
"es2016.array.include"
],
"downlevelIteration": true,
"strict": true
}
}
The solution is declaring an interface :
interface UserProps {
username: string;
}
class User implements UserProps {
username: string;
// more properties
constructor (data: UserProps) {
// Check if data Obejct exactly all the class properties and they are of the right type;
// Set instance properties
}
}
In WinJS there are three binding related mixins:
WinJS.Binding.observableMixin
WinJS.Binding.dynamicObservableMixin
WinJS.Binding.mixin
Both WinJS.Binding.mixin and WinJS.Binding.dynamicObservableMixin define the same methods to mix. The only difference between their definition is that WinJS.Binding.mixin is defined as a non enumerable property on the WinJS.Binding namespace, while WinJS.Binding.dynamicObservableMixin is defined as an enumerable property:
WinJS.Namespace.define("WinJS.Binding", {
mixin: { value: dynamicObservableMixin, enumerable: false, writable: true, configurable: true },
dynamicObservableMixin: { value: dynamicObservableMixin, enumerable: true, writable: true, configurable: true },
});
I don't see any real difference between these two mixins - I don't see the relevance of the difference of the enumerable flag on this property. Is there any semantic or other difference as to which mixin of the two one is using?
You are right. There is no real difference between mixin and dynamicObservableMixin. They are same.
WinJS.Binding.mixin adds methods like addProperty, removeProperty, get/setProperty which are used by WinJS.Binding.expandProperties. expandProperties is used to make an existing class observable. dynamic nature is attributed to dynamically adding properties to an object.
Example:
var MyListViewModel = WinJS.Class.define(
function MyListViewModel_ctor()
{
this._initObservable();
},
{
load: function load()
{
var self = this;
return serviceclient.getMyListData().then(function (records)
{
self.items = new WinJS.Binding.List(records);
});
}
});
WinJS.Class.mix(MyListViewModel,
WinJS.Binding.mixin,
WinJS.Binding.expandProperties({ items: '' }));
There is difference between observableMixin and mixin. observableMixin only has bind, unbind and notify methods.
1-I used following code to define a reusable grid,
but when I make instance, no config in class definition either do not have effect of break the code. What is the reason?
3- Is there any restriction in class config declaration?
2- How I can make some default columns in grid class and add some more columns to its objects?
Thanks
Ext.define("IBS.users.Grid", {
extend: "Ext.grid.Panel",
config:{
selType:'checkboxmodel', //not work
dockedItems:[/* items */], //break
multiSelect:true,
features: [
{
groupHeaderTpl: '{name}',
ftype: 'groupingsummary'
},
{
ftype:'filters',
encode: false, // json encode the filter query
local: true
}
],
viewConfig: { //not work
stripeRows: true,
filterable:true,
loadMask: false
},
listeners : {
itemdblclick: function(dv, record, item, index, e) {
console.log(arguments);
}
}
},
constructor:function(config) {
this.callParent(arguments);
this.initConfig(config);
// this.self.instanceCount++;
}
});
1-I used following code to define a reusable grid, but when I make instance, no config in class definition either do not have effect of break the code. What is the reason?
I can answer why your config doesn't have effect. Because config which is being passed into cunstructor is not your default config. You have to apply your default config in order to make default config to have effect:
constructor:function(config) {
config = Ext.applyIf(config, this.config);
this.callParent(arguments);
this.initConfig(config);
}
However, I don't know why dockedItems:[/* items */] breaks the code. Maybe you have syntax or logical errors somewhere within /* items */.
2- How I can make some default columns in grid class and add some more
columns to its objects?
That is easy. Just override your initComponent function:
Ext.define("IBS.users.Grid", {
extend: "Ext.grid.Panel",
// ...
initComponent : function(){
if (!this.columns) {
// default columns:
this.columns = [{
dataIndex: 'dkjgkjd',
// ...
}];
// if we passed extraColumns config
if (this.extraColumns)
for (var i=0; i < this.extraColumns.length; i++)
this.columns.push(this.extraColumns[i]);
}
this.callParent(arguments);
},
// ...
});
3- Is there any restriction in class config declaration?
I'm not aware of any. However, I wouldn't recommend to declare object configs in class definition. For example:
Ext.define("IBS.users.Grid", {
extend: "Ext.grid.Panel",
bbar: Ext.create('Ext.toolbar.Toolbar', // ...
// ...
});
It will be ok with first instance of the class. But when you create the second instance it's bbar refers to the same object as the first instance. And therefore bbar will disappear from the first grid.
Instead declare object configs in initComponent.