Dart Inline type definition - dart

With TypeScript, I can do this:
export class Ticket extends BaseEntity {
#PrimaryGeneratedColumn()
id: number;
//...
clientEndUtils: {
maxBuyableQtyForCurrentBuyer: number;
}/* THIS IS INLINE TYPE DEFINITION */
}
Is there a way to do that with Dart Language?
I mean defining a type inside a class.

Related

Dart: how to override a generic method?

Consider my following base class:
abstract class IChat<Message extends IMessage> {
String get getId;
List<T> getUsers<T extends IUser>();
}
Now my extended Model looks like this:
class Chat extends IChat<ChatMessage> {
String id;
List<ChatUser> members;
Chat({this.chat, this.members});
#override
String get getId => id;
#override
List<T> getUsers<T extends IUser>() => members;
}
List<T> getUsers<T extends IUser>() => members; throws an error because I return List<ChatUser> instead of List<T>. How do I override the method to make this work? My ChatUser class obviously also extends IUser.
Edit
#jamesdlin gave one solution: #override List<T> getUsers<T extends IUser>() => members.cast<T>(). It is possible without type casting?
First consider what you actually want your classes to do.
It seems like the subclass has a specific type of IUser that it always wants to return, but a generic function takes its type argument per invocation. So, the type should probably be a property of the class, not of the invocation.
Consider:
abstract class IChat<Message extends IMessage> {
String get getId;
List<IUser> getUsers();
}
class Chat extends IChat<ChatMessage> {
String id;
List<ChatUser> members;
Chat({this.chat, this.members});
#override
String get getId => id;
#override
List<ChatUser> getUsers() => members;
}
Would that satisfy your needs?
As stylistic comments, your code is very C#-like, and doesn't look like Dart. I'd probably declare the classes as:
abstract class Chat<M extends Message> {
String get id;
List<User> get users;
}
class SomeChat extends Chat<ChatMessage> {
#override
final String id;
#override
List<ChatUser> users;
// ...
SomeChat({this.id, List<CharUser> members, ...}) : users = members;
// ...
}

TypeORM STI inheritance issues

I´m trying to setup a STI inheritance hierarchy, similar to described on the official docs here, but getting the following error
TypeError: Cannot read property 'ownColumns' of undefined
at /Users/luizrolim/workspace/nqa/src/metadata-builder/EntityMetadataBuilder.ts:320:64
at Array.map (<anonymous>)
at EntityMetadataBuilder.computeEntityMetadataStep1 (/Users/luizrolim/workspace/nqa/src/metadata-builder/EntityMetadataBuilder.ts:316:14)
at /Users/luizrolim/workspace/nqa/src/metadata-builder/EntityMetadataBuilder.ts:108:45
at Array.forEach (<anonymous>)
Here are me entities:
#ChildEntity()
export class ChildExam extends BaseExam {
}
#Entity('exm_exams')
#TableInheritance({ column: { type: 'varchar', name: 'type' } })
export abstract class BaseExam extends NQBaseEntity {
#Column()
public alias: string
#Column()
public description: string
}
import { BaseEntity, Column, PrimaryGeneratedColumn } from 'typeorm'
import { DateColumns } from '#infra/util/db/DateColumns'
export abstract class NQBaseEntity extends BaseEntity {
#PrimaryGeneratedColumn()
public id: number
#Column(type => DateColumns)
public dates: DateColumns
}
I am running at "typeorm": "^0.2.12",
I also ran into this error when trying to make Single Table Inheritance work:
(node:22416) UnhandledPromiseRejectionWarning: TypeError: Cannot read
property 'ownColumns' of undefined at
metadata-builder\EntityMetadataBuilder.ts:356:64
My problem was, that I only listed my child entities in the connection options but I forgot to also add my parent entity.
Here is how I solved it (using TypeORM v0.3.0-rc.19):
ParentEntity.ts
import {BaseEntity, Entity} from 'typeorm';
#Entity()
#TableInheritance({ column: { type: 'varchar', name: 'type' } })
export abstract class ParentEntity extends BaseEntity {
// ...
}
ChildEntity.ts
import {ChildEntity} from 'typeorm';
#ChildEntity()
export class ChildEntity extends ParentEntity {
constructor() {
super();
}
// ...
}
initDatabase.ts
import 'reflect-metadata';
import {Connection, createConnection} from 'typeorm';
import {SqliteConnectionOptions} from 'typeorm/driver/sqlite/SqliteConnectionOptions';
import {PostgresConnectionOptions} from 'typeorm/driver/postgres/PostgresConnectionOptions';
import {ConnectionOptions} from 'typeorm/connection/ConnectionOptions';
import {ParentEntity, ChildEntity} from './entity/index';
function getConnectionOptions(env?: string): ConnectionOptions {
// Here is the important part! Listing both, parent and child entity!
const entities = [ParentEntity, ChildEntity];
const test: SqliteConnectionOptions = {
database: ':memory:',
dropSchema: true,
entities,
logging: false,
name: 'default',
synchronize: true,
type: 'sqlite',
};
const development: SqliteConnectionOptions = {
database: 'test.db3',
type: 'sqlite',
};
const production: PostgresConnectionOptions = {
type: 'postgres',
url: process.env.DATABASE_URL,
};
const devProd = {
name: 'default',
entities,
logging: false,
migrations: [],
subscribers: [],
synchronize: true,
};
switch (env) {
case 'production':
return Object.assign(production, devProd);
case 'test':
return test;
default:
return Object.assign(development, devProd);
}
}
export default function initDatabase(): Promise<Connection> {
const options = getConnectionOptions(process.env.NODE_ENV);
return createConnection(options);
}
In my application I now have to call await initDatabase() at first, to properly initialize the database schema.
You should make class BaseExam not abstract to make it work.

List property inheritance

The parser is complaining that the property inheritor .list is not subtype of ModelList.list, but LeadsGroup does inherit from Model.
Is this wrong? What is the correct way to do this?
My base class:
abstract class ModelList {
List<Model> get list;
set list(List<Model> n);
}
The inheritor:
class ListLeadsGroup extends ModelList {
List<LeadsGroup> list;
}
class LeadsGroup extends Model {
}
If you have code like
class Foo extends ModelList {}
ModelList ml = new ListLeadsGroup();
ml.list.add(new Foo());
ml.list is of type Model, therefore adding Foo should be legit.
But this very likely is not what you want.
This is why List<ListLeadsGroup> can't override List<Model>.
This should do what you want:
abstract class ModelList<T extends Model> {
List<T> get list;
set list(List<T> n);
}
class ListLeadsGroup extends ModelList<LeadsGroup> {
List<LeadsGroup> list;
}
class LeadsGroup extends Model {
}
just copied from Matan Lurey's comment on Gitter
import 'package:func/func.dart';
class ModelRegistry {
final _factories = <Type, Func0<Model>>{};
Model create(Type type) => _factories[type]();
void register(Type type, Model factory()) {
_factories[type] = factory;
}
}
main() {
var registry = new ModelRegistry();
registry.register(FooModel, () => new FooModel());
var foo = registry.create(FooModel);
}
found a solution using the new keyword covariant. Now the classes that extends ModelList can override the List<Model> list without warnings.
#serializable
abstract class ModelList extends ModifiedModel
implements Model {
Type get listType {
throw new UnimplementedError();
}
List<Model> get list;
set list(covariant List n);
}

What is the difference between #Inject and #Injectable in Angular 2 typescript

I don't understand When to use #Inject and when to use #Injectable ?
import {Component, Inject, provide} from '#angular/core';
import {Hamburger} from '../services/hamburger';
export class App {
bunType: string;
constructor(#Inject(Hamburger) h) {
this.bunType = h.bun.type;
}
}
And..
import {Injectable} from '#angular/core';
import {Bun} from './bun';
#Injectable()
export class Hamburger {
constructor(public bun: Bun) {
}
}
The #Injectable decorator aims to actually set some metadata about which dependencies to inject into the constructor of the associated class. It's a class decorator that doesn't require parameters. Without this decorator no dependency will be injected...
#Injectable()
export class SomeService {
constructor(private http:Http) {
}
}
The #Inject decorator must be used at the level of constructor parameters to specify metadata regarding elements to inject. Without it, the type of parameters is used (obj:SomeType is equivalent to #Inject(SomeType) obj).
#Injectable()
export class SomeService {
constructor(#Inject(Http) private http:Http, #Inject('sometoken') obj) {
}
}
You must read this difference- #Inject and #Injectable
#Inject()
is a manual mechanism for letting Angular know that a parameter must be injected.
When using TypeScript, #Inject is only needed for injecting primitives.
For eg:
export class AppComponent {
encryption = this.chatWidget.chatSocket.encryption;
constructor(#Inject(ChatWidget) private chatWidget) { }
}
#Injectable()
lets Angular know that a class can be used with the dependency
injector.
For eg:
#Injectable()
export class ChatWidget {
constructor(
public authService: AuthService,
public authWidget: AuthWidget,
public chatSocket: ChatSocket) { }
}
In the above example Angular's injector determines what to inject into ChatWidget's constructor by using type information

What is the difference between extends Object with Observable and extends Observable

What is the difference between extends Object with Observable and extends Observable as applied to the class below.
The result is the same when the application is run.
library models;
import 'package:polymer/polymer.dart';
class Person extends Object with Observable {
#observable String name;
#observable bool signedAgreement = false;
Person();
Person.from(Person other) {
name = other.name;
signedAgreement = other.signedAgreement;
}
blank() {
name = '';
signedAgreement = false;
}
}
library models;
import 'package:polymer/polymer.dart';
class Person extends Observable {
#observable String name;
#observable bool signedAgreement = false;
Person();
Person.from(Person other) {
name = other.name;
signedAgreement = other.signedAgreement;
}
blank() {
name = '';
signedAgreement = false;
}
}
There no difference in the behaviour between this two declarations.
Here's a quote from Florian Loitsch :
When you extend "Object" with a mixin the first mixin can always take the place of "Object".
The only little difference is in class hierarchy (superclass are not the same) :
import 'dart:mirrors';
abstract class Mixin {}
class A extends Mixin {}
class B extends Object with Mixin {}
main() {
print(reflectClass(A).superclass);
// => ClassMirror on 'Mixin'
print(reflectClass(A).superclass.superclass);
// => ClassMirror on 'Object'
print(reflectClass(B).superclass);
// => ClassMirror on 'dart.core.Object with .Mixin'
print(reflectClass(B).superclass.superclass);
// => ClassMirror on 'Object'
}

Resources