I have function that creates instances of given class and I don't how to tell TypeScript that:
function builder returns instances of class passed in first argument
class A extends HTMLElement {
color: 'white'
}
function builder<T extends typeof HTMLElement>(classParam: T) {
let instance = new classParam()
return instance
}
let instance = builder(A)
instance.color = 'black'
// Property 'color' does not exist on type 'HTMLElement'
Is it possible without using type assertion?
I've fixed and explained the problems:
class A extends HTMLElement {
color: string = 'white' // you gave it the type "white",
// but I assume you need the value "white" (and type `string`)
}
function builder<T extends HTMLElement>(classParam: { new(): T }) : T {
// previous line:
// - `typeof` in the generic constraint is not valid
// - the parameter could not be of type `T`, because you would not be
// able to use `new`. It's now a parameter which has a constructor
// which creates a `T`
// - we are now returning `T`, instead of (implicit) `any`
let instance = new classParam()
return instance
}
let instance = builder(A)
instance.color = 'black'
Link to playground
Related
I'm following a course in kotlin and they speak about how to make a special setter but I don't know how to make it working here is my code :
class Course (val id:Int, title:String, var duree:Int, var state:Boolean){
var title:String = title
get(){return field}
set(value){field = "my awesome" + value}
}
fun main(args: Array<String>) {
var myCourse:Course = Course (0, "stuff", 50, true)
println(myCourse.title)
}
but it keep output 'stuff' instead of 'my awesome stuff'
var myCourse:Course = Course(0, "stuff", 50, true)
With the above line of code, the Course object is initialized with the constructor. Here the setter is not called, hence it prints stuff and not my awesome stuff. The setter would get called only if you use
myCourse.title = "stuff"
If you want the setter to be called on initialization, you need to set the value of title in an init block as below
class Course(val id: Int, title: String, var duree: Int, var state: Boolean) {
var title: String = title
set(value) {
field = "my awesome $value"
}
init {
this.title = title
}
}
Or, you can drop the custom setter and set the value of title with your custom value in the init block itself
class Course(val id: Int, var title: String, var duree: Int, var state: Boolean) {
init {
this.title = "my awesome ${this.title}"
}
}
The custom setter is only used when you explicitly set the value. The custom setter is not used when you initialize the backing field at the declaration site using = title.
If you want the custom setter to be applied using the initial value, you can add an init block to your class:
init {
this.title = title
}
I was able to get you example working applying a little change in your code:
class Course (val id:Int, __title:String, var duree:Int, var state:Boolean){
var title:String = ""
get() { return field}
set(value){field = "my awesome" + value}
init {
title = __title
}
}
The difference seems to be the explicit assignment title = __title, that forces the usage of the custom setter...
I want to access animals class color from dogs reference
as I am new to kotlin if something is wrong guide me
fun main() {
var dogs = Dogs("pug")
println("Color of Dog :${dogs.color}")//Black
println("Color of Animal:${}")//White
}
private open class Animals {
open var color: String = "White"
}
private class Dogs(var breed: String) : Animals() {
override var color: String = "Black"
}
You can only do this by exposing another property (or function) in Dogs that accesses the super class property to get the value being held in that field, and using that:
private class Dogs(var breed: String) : Animals() {
override var color: String = "Black"
var animalColor: String
get() = super.color
set(value) {
super.color = value
}
}
But this is an abuse of inheritance, and runs counter to common expectations of OOP. A single property should not have a different meaning in a subclass, such that external classes have to distinguish between them. If Dogs has some characteristic that is different than the property in Animals, then it should have a new, different property for that rather than overriding.
Also, you don't need to override just to change the initial value of a var. Overriding creates a second, redundant backing field. Your Dogs class should be like this if you want Dogs to have a different default value for color:
private class Dogs(var breed: String) : Animals() {
init {
color = "Black"
}
}
I am trying to create a polymer 2.0 custom element with function property. But not able to find an example to refer to. The Polymer 2.0 documentation mentions "Function" as a supported property but there is no syntax/example available.
Can somebody point me to a example where a callback function is passed as a property?
Need to pass a call back function to an element.For example
<custom-element size = "20" response = "callback"></custom-element>
class CustomElement extends Polymer.Element {
static get is() { return 'custom-element'; }
static get properties() {
return {
prop1: {
type: String,
value: 'firebasetest-element'
},
callback:
{
type: Function,
notify: true
}
}
I don't know if this is what you are talking about, but you can use data binding using methods like this:
<my-element some-attribute="[[myMethod(observerProperty.subProperty)]]"></my-element>
and in your method declaration:
myMethod() {
var something = "can be anything"
return something
}
With this, your "someAttribute" property of my-element will be a string "can be anything", and myMethod gets called anytime "observerProperty.subProperty" gets changed.
At example I have three classes : View , FView ( extends View) and MView (extends View) . I have variable from type MView and want to to check it against parent class View ( i.e if this variable is from class View ). Is it possible to get the parent class ( View class) ? . Here is full example: https://try.haxe.org/#eA594
class Test {
static function main() {
var v = new SView();
trace(Type.getClassName( Type.getSuperClass(Type.getClass(v))) );
}
}
class View :
class View {
public function new() {
}
}
class FView :
class FView extends View {
public function new() {
super();
}
}
class SView :
class SView extends FView {
public function new() {
super();
}
}
If you want to get to the base class, you can simply recurse or iterate until Type.getSuperClass() returns null:
// at runtime: find out what is the base class of `v`
var base:Class<Dynamic> = Type.getClass(v);
while (true) {
var s = Type.getSuperClass(base);
if (s == null)
break;
base = s;
}
trace(Type.getClassName(base));
However, you mention that you want to do this simply to check if MView (or SView) are of the View type.
Well, for this, there are a few simpler alternatives...
First, at compile type, you can simply use a type check (or an assignment) to check if v:SView unifies with View:
// at compile time: enforce that `v` be of type `View` or compatible with it
var v1 = (v:View); // use a type check
var v2:View = v; // or simply pass it to something expecting `View`
If you need to do it at runtime, that's possible as well with Std.is():
// at runtime: check if `v` is a subclass instance of `View`
trace(Std.is(v, View));
For a complete example, check out this Try Haxe instance.
My level of typescript is 'ABSOLUTE BEGINNER' but I have a good OOP background. I am building an with typescript that reference an external t.ds library that contains the following interface:
interface ISimpleObject {
foo: string;
bar?: any;
}
Now, if I want to call a method that has an IRequestConfig parameter, how do I create one? I can see different options:
Create a simple implementation of ISimpleObject. I don't like this approach because it looks like boilerplate code to me
don't initialize the object (I fear this could break something...):
var x :IsimpleObject;
x.bar = 'xxx';
callMethod(x);
Cast a pojo:
var x :IsimpleObject = <IsimpleObject>{foo: 'yyy', bar:'xxx'};
I don't like this approach either because it doesn't enforce type safety...
I guess this is a fairly trivial question and I am missing something trivial about typescript.
Typescript2:
const simpleObject = {} as ISimpleObject;
If you have an interface like:
interface ISimpleObject {
foo: string;
bar?: any;
}
This interface is only used at compile time and for code-hinting/intellisense. Interfaces are used to provide a rigorous and type-safe way of using an object with a defined signature in a consistent manner.
If you have a function using the interface defined above:
function start(config: ISimpleObject):void {
}
The TypeScript compile will fail if an object does not have the exact signature of the ISimpleObject interface.
There are multiple valid techniques for calling the function start:
// matches the interface as there is a foo property
start({foo: 'hello'});
// Type assertion -- intellisense will "know" that this is an ISimpleObject
// but it's not necessary as shown above to assert the type
var x = <ISimpleObject> { foo: 'hello' };
start(x);
// the type was inferred by declaration of variable type
var x : ISimpleObject = { foo: 'hello' };
start(x);
// the signature matches ... intellisense won't treat the variable x
// as anything but an object with a property of foo.
var x = { foo: 'hello' };
start(x);
// and a class option:
class Simple implements ISimpleObject {
constructor (public foo: string, public bar?: any) {
// automatically creates properties for foo and bar
}
}
start(new Simple("hello"));
Any time the signature doesn't match, the compile will fail:
// compile fail
var bad = { foobar: 'bad' };
start( bad );
// compile fail
var bad: ISimpleObject = { foobar: 'bad' };
// and so on.
There is no "right" way to do it. It's a matter of style choice. If it were an object that was constructed (rather than just directly passed as a parameter), I'd normally declare the type:
var config: ISimpleObject = { foo: 'hello' };
That way code-completion/IntelliSense will work anywhere I used the config variable:
config.bar = { extra: '2014' };
There is no "casting" in TypeScript. It is called a type assertion and shouldn't be needed in the cases described here (I included an example above where it could be used). There's no need to declare the variable Type and then use an assertion in this case (as the type was already known).
You can't create an instance of an interface since Typescript doesn't "translate" it into js. You can check the js that is created and you will see nothing in it. It's simple for compile errors, type safety and intelisense.
interface IStackOverFlow
{
prop1 : string;
prop2 : number;
}
public MyFunc(obj : IStackOverFlow)
{
// do stuff
}
var obj = {prop1: 'str', prop2: 3};
MyFunc(obj); // ok
var obj2 = {prop1: 'str'};
MyFunc(obj); // error, you are missing prop2
// getObj returns a "any" type but you can cast it to IStackOverFlow.
// This is just an example.
var obj = <IStackOverFlow> getObj();