Typescript error when using interface from module as field within class - module

I am working on providing a type definition file for fabric.js. The general structure is shown in the following sample:
declare module fabric {
export interface Canvas {
selectionBorderColor: string;
selectionColor: string;
...
}
var Canvas: {
new (): Canvas;
}
}
This pattern allows me to use fabric.Canvas in a 'interface-like' way, so that variables are associated with the fabric.Canvas interface. At the same time it allows me to call "static members" (such as the constructor of fabric.Canvas).
But this leads to a problem when using a field of interface 'fabric.Canvas' within a class. The following sample shows such an case:
This problem only occurs when placing the interface within a module, otherwise everything works fine.
Any solutions for this problem?

There is some type confusion because you have an interface and a field with the same name - I know this is common in the lib.d.ts file, but I don't think it is a good practice when writing new TypeScript code. It seems to be something of a necessity for defining existing code.
If you rename var Canvas to var MyCanvas (or anything else) your code works.
I tend to prefix my interfaces with an I, for example ICanvas - but this isn't a TypeScript convention (yet).
declare module fabric {
export class Canvas {
selectionBorderColor: string;
selectionColor: string;
}
}
class MyClass {
canvas: fabric.Canvas;
}

Related

Angular 14 Form Control - Inheriting recursively types from interface

I was wondering if anyone managed use complex interfaces to take advantage of the new typed FormControl and avoid boilerplate code on components.
I manage to export a 1-level-only interface with:
interface ISimple {
a: number; b: string; c: Date
}
export type AsFormControls<T> = {
[K in keyof T]: FormControl<T[K]>;
}
and then declaring my form in my component as
form: FormGroup<AsFormControls<ISimple>>;
Some of my simple forms were just plug and play, very useful, but when I have something like the following I can't figure out how to proceed, because I need the a FormGroup type for properties that contain properties.
interface INotSoSimple {
d: {
e: string;
f: Date;
}
}
Could there be a way to modify this interface for it to work with the new Form Controls? Any leads?

Is it possible to have a field with a generic type that refers to the actual runtime type of the containing class?

I'm fiddling around with this code where I have a base class Node which can be extended:
open class Node
class SubNode : Node()
Now, I have a Behavior class that can be attached to a node, and when this attachment happens, the behavior object is invoked:
open class Behavior {
fun attach(node: Node) {
println("Behavior was attached to a node")
}
}
open class Node {
var behavior: Behavior? = null
set(value) {
field = value
value.attach(this)
}
}
This works, but could this be generified in such way that the type of the attach method would always refer to the actual type of the attached Node? For instance, if the Behavior class was extended like this:
open class Behavior<NodeType: Node> {
open fun attach(node: NodeType) {
}
}
class SubBehavior : Behavior<SubNode>() {
override fun attach(node: SubNode) {
}
}
I've tried various ways of setting up the types in Node class, but can't figure any other way than passing the actual subclass type to the base class (which seems rather cumbersome):
open class Node<SubType: Node> {
var behavior: Behavior<SubType>? = null
}
class SubNode : Node<SubNode>()
Is there a way to do this in any other way?
I think what you need are self types, which don't exist in Kotlin (at least, not yet).
Using recursive generics like you did is the most common way around the problem.
That said, I have trouble understanding your use case here for intertwining these 2 classes together this way. Like how is behaviour used inside your node, etc.

Null property provided by Gradle when using custom plugin

I'm trying to follow the Gradle custom plugin documentation to create a plugin that can be configured.
My plugin code:
interface MyExtension {
var myValue: Property<String>
}
class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
val extension = project.extensions.create<MyExtension>("myExt")
}
}
in build.gradle.kts:
plugins {
`java-library`
}
apply<MyPlugin>()
the<MyExtension>().myValue.set("some-value")
Running this will give
Build file '<snip>/build.gradle.kts' line: 6
java.lang.NullPointerException (no error message)
Turns out the the<MyExtension>().myValue is null, so the set call fails. How do I do this correctly? Did I miss something in the documentation, or is it just wrong?
The documentation is not wrong. Properties can be managed by either you or by Gradle. For the latter, certain conditions have to be met.
Without managed properties
If you want to be completely in charge, you can instantiate any variables you declare yourself. For example, to declare a property on an extension that is an interface, it could look like this:
override fun apply(project: Project) {
val extension = project.extensions.create("myExt", MyExtension::class.java)
extension.myValue = project.objects.property(String::class.java)
}
Or you could instantiate it directly in the extension by making it a class instead:
open class MessageExtension(objects: ObjectFactory) {
val myValue: Property<String> = objects.property(String::class.java)
}
However, a property field is not really supposed to have a setter as the property itself has both a setter and a getter. So you should generally avoid the first approach and remove the setter on the second.
See here for more examples on managing the properties yourself.
With managed properties
To help you reduce boilerplate code, Gradle can instantiate the properties for you with what is called managed properties. To do use these, the property must not have a setter, and the getter should be abstract (which it implicitly is on an interface). So you could go back to your first example and fix it by changing var to val:
interface MyExtension {
val myValue: Property<String> // val (getter only)
}
Now Gradle will instantiate the field for you. The same thing works for abstract classes.
Read more about managed properties in the documentation here.

Javascript structure representation using Kotlin JS

my question is about creating javascript structure within KotlinJS and use them calling external modules.
Let's say we have the following js code and we want to translate it into KotlinJS.
const config = {
defs : "something",
resolvers : {
Query: {
books: () => []
}}
};
myFunction(config) // This can be any kind of external js function that accepts the above structure
How do we represent that config structure above using Kotlin JS? Is there an easy way to handle structures/json Kotlin side? Can we declare in some way that structure as dynamic?
Using Kotlin objects doesn't help.
As of now you gotta introduce interface and it's implementation, so it would be something like this:
external interface ConfigInterface {
var defs: String,
var resolvers: QueryHolder
}
external interface QueryHolder {
var Query: BookProcessor
}
external interface BookProcessor {
var books: () -> Array<Any>
}
For more complicated structures it can easily become a challenge.
Here's what can be done to automate such translations.
You can:
generate typescript declaration for this code with typescript compiler (using tsc -d)
generate kotlin declaration with dukat.
Dukat is a tool from Kotlin/JS team created specifically for this, there's ongoing battle for improving the quality of this tool. Here is what would be generated in your particular case:
external interface `T$0` {
var books: () -> Array<Any>
}
external interface `T$1` {
var Query: `T$0`
}
external object config {
var defs: String
var resolvers: `T$1`
}
Which is far from optimal - for instance the name of generated entities is something we didn't wanted to encourage people to reuse but the more it goes, the more it looks like a mistake (which we will fix this way or another).

Catching up with 'require' for a metamodel class

I have defined own metamodel class to create a special kind of classes. Now, I would like these classes to automatically register themselves with a special kind of manager. Basically, this would like like this (would only compose be called each time when class' module is being loaded):
use MyManager;
class MyHOW is Metamodel::ClassHOW {
method compose ( Mu \type ) {
self.add_parent( type, MyParentClass );
callsame;
registerMyClass( type );
}
}
Then I have something like:
use v6;
use MyClass;
myclass Foo { ... }
in a module. Then there is a manager object which scans repositories/file system and requires modules with names matching to a certain pattern. Afterwards, it needs to know what myclasses are defined in each module. It could scan the symbol table of the loaded module. But this won't work if the loaded file contains multiple modules or no modules at all – like in the example above.
So far, it looks like the INIT phaser would provide the solution, but I'm struggling to find how to get the body block of a class from within the composer method.
When doing meta-programming, the meta-object's methods are invoked during compilation, as declarations are parsed. Therefore, the compose method is called immediately after the parsing of a myclass foo { } declaration. The result of the module's compilation is then saved, and nothing in the meta-object will be processed again when the module is loaded.
There's no supported way that I'm aware of to inject a load-time callback into the module where a type is being declared. However, it's possible to install the symbols into a separate package - used as a registry - and then find them there.
For example, given I have a lib/MyClass.pm6 that looks like this:
package MyRegistry { }
class MyParentClass { }
class MyHOW is Metamodel::ClassHOW {
method compose ( Mu \type ) {
MyRegistry::{self.name(type)} = type;
self.add_parent( type, MyParentClass );
callsame;
}
}
my package EXPORTHOW {
package DECLARE {
constant myclass = MyHOW;
}
}
And I write some files mods/A.pm6 and mods/B.pm6 like this:
use MyClass;
myclass A { }
And this:
use MyClass;
myclass B { }
Then when I require them in a script like this, and dump the keys in MyRegistry, they'll both be registered there:
use MyClass;
for dir('mods', test => /pm6$/) {
require $_;
}
dd MyRegistry.WHO.values;
Thus giving a predictable way to find them all.
Note that for a technique like this to work, you really need to have them stored into a Stash, since the loader knows how to symbol-merge those, whereas other types touched in different ways during the compilation of different modules will result in load-time conflicts.
You are left with the slight challenge of making sure to install everything under a sufficiently unique key; the type name as I used here is probably not unique enough in general. Probably I'd just generate something sufficiently random that the chance of a collision is hugely unlikely.