Is this an error in Typescript compiler - typescript2.0

I noticed an issue where a user defined typeguard on a union type doesn't behave symmetrically. I hope this an error on my end :-/
The issue shows up in test2() where the type is not inferred properly from the typeguard.
class PropPacket {
constructor(public key: string, public value: number) {}
}
class EventPacket {
constructor(public key: string) {}
}
type Packet = PropPacket | EventPacket;
function isPropPacket(p: EventPacket | PropPacket): p is PropPacket {
return p instanceof PropPacket;
}
function isEventPacket(p: EventPacket | PropPacket): p is EventPacket {
return p instanceof EventPacket;
}
function test1(p: Packet) {
if (isPropPacket(p)) {
// `p` is PropPacket
p.key;
p.value;
} else {
// `p` is EventPacket
p.key;
}
}
function test2(p: Packet) {
if (isEventPacket(p)) {
p.key;
} else {
// ERROR: thinks `p` is `never` type
p.key;
p.value;
}
}
You can see the issue by pasting the code in the typescript playground (https://www.typescriptlang.org/play/)

This happens because all EventPackets are in fact PropertyPackets. Typescript has a structural type system which does not consider two classes to be distinct by declaration, only by the properties and methods they contain.

Related

why dose debug break point not hitting on my lamda function (java8 use idea)?

Version:IDEA 2019.3
JDK8
Tried methods :
I'm trying to wrap it in curly braces
Globally, only one breakpoint is hit,None of them took effect
The program goes directly to the saving method,
public <V0 extends Rmap> Output<V0> prior(Trans<V0, Rmap> conv) {
return saving(ds0 -> {
enqueue((DSdream) ds0.map((Function<Rmap, Rmap>) row -> {
Rmap r = conv.apply((V0) row);
return Rec.of(r, tds.get(r.table().toString()));
}, f));
});
}
How do I stop at the lambda break point?
Thanks
I tried to use an anonymous inner class that would normally stop at the breakpoint,
#Override
public <V0 extends Rmap> Output<V0> prior(Trans<V0, Rmap> conv) {
Output<Rmap> saving = saving(new Consumer<DSdream>() {
#Override
public void accept(DSdream dSdream) {
enqueue((DSdream)
dSdream.map((Function<Rmap, Rmap>) row -> {
Rmap r = conv.apply((V0) row);
return Rec.of(r, tds.get(r.table().toString()));
}, f));
}
});
return (Output<V0>) saving;
}
Presumably, after decompiling, lambda is compiled into inner class,
So the break point cannot be located .
It should be the disadvantage of lambda

can not read get property of undefined angular 2 error

hi I am trying to get city name from google api but getting that error below is my code
appcomponent class
import {Component, OnInit} from 'angular2/core';
import {marketComponent} from './market.component';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {introComponent} from './intro.component';
import {geoService} from './service.geo';
import {JSONP_PROVIDERS} from 'angular2/http';
declare var google: any;
#Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [ROUTER_DIRECTIVES],
providers: [JSONP_PROVIDERS, geoService]
})
#RouteConfig([
{ path: '/intro', name: 'Intro', component: introComponent, useAsDefault: true },
{ path: '/market', name: 'Market', component: marketComponent },
])
export class AppComponent {
constructor(private _http: geoService) { }
public maps;
public cat_error: Boolean = false;
public xml_Latitude :string;
public xml_Lang: string;
ngOnInit() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.showPosition);
} else {
alert("Geolocation is not supported by this browser.");
}
var input: any = document.getElementById('google_places_ac');
var autocomplete = new google.maps.places.Autocomplete(input, {});
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
console.log(place)
});
}
showPosition(position) {
this.xml_Latitude = position.coords.latitude;
this.xml_Lang = position.coords.longitude;
this._http.getPlaces(this.xml_Latitude, this.xml_Lang).subscribe(
data => { this.maps = data },
err => { this.cat_error = true }
);
var result = this.maps.results;
var city = result[0].address_components[4].long_name + "," + result[0].address_components[6].long_name;
alert(city);
}
}
and geoservice file
import {Injectable} from 'angular2/core';
import { Response, Jsonp} from 'angular2/http';
import 'rxjs/add/operator/map';
#Injectable()
export class geoService {
constructor(private http: Jsonp) { }
public xml_Latitude: string;
public xml_Lang: string;
public getPlaces(xml_Latitude, xml_Lang) {
return this.http.get(`http://maps.googleapis.com/maps/api/geocode/json?latlng=
'${this.xml_Latitude}','${this.xml_Lang}'&sensor=true`)
.map((res: Response) => res.json())
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return error.json().error || 'Server error';
}
}
error also says getplaces is not a function, I think I am missing something but don't know what....
In addition to the callback ordering problem identified by Thierry, you have a lost this context on this line:
navigator.geolocation.getCurrentPosition(this.showPosition);
The Problem
You have the classic JavaScript problem known as the incorrect this context.
The this keyword in JavaScript behaves differently than in does in other languages like C# and Java.
How this works
The this keyword, in a function, is determined as follows:
* If the function was created through a call to .bind, the this value is the argument provided to bind
* If the function was invoked through a method call, e.g. expr.func(args), then this is expr
* Otherwise
* If the code is in strict mode, this is undefined
* Otherwise, this is window (in a browser)
Let's look at how this works in practice:
class Foo {
value = 10;
doSomething() {
// Prints 'undefined', not '10'
console.log(this.value);
}
}
let f = new Foo();
window.setTimeout(f.doSomething, 100);
This code will print undefined (or, in strict mode, throw an exception).
This is because we ended up in the last branch of the decision tree above.
The doSomething function was invoked, the function wasn't a result of a bind call, and it wasn't invoked in a method syntax position.
We can't see the code for setTimeout to see what its invocation looks like, but we don't need to.
Something to realize is that all doSomething methods point to the same function object.
In other words:
let f1 = new Foo();
let f2 = new Foo();
// 'true'
console.log(f1.doSomething === f2.doSomething);
We know that setTimeout can only see the function we passed it, so when it invokes that function,
there's no way for it to know which this to provide.
The this context has been lost due to our referencing the method without invoking it.
The Red Flag
Once you know about this problems, they're easy to spot:
class Foo {
value = 10;
method1() {
doSomething(this.method2); // DANGER, method reference without invocation
}
method2() {
console.log(this.value);
}
}
The Solution
You have a few options here, each with its own trade-offs.
The best option depends on how often the method in question is invoked from differing call sites.
Arrow Function in Class Definition
Instead of using the normal method syntax, use an arrow function to initialize a per-instance member.
class DemonstrateScopingProblems {
private status = "blah";
public run = () => {
// OK
console.log(this.status);
}
}
let d = new DemonstrateScopingProblems();
window.setTimeout(d.run); // OK
Good/bad: This creates an additional closure per method per instance of your class. If this method is usually only used in regular method calls, this is overkill. However, if it's used a lot in callback positions, it's more efficient for the class instance to capture the this context instead of each call site creating a new closure upon invoke.
Good: Impossible for external callers to forget to handle this context
Good: Typesafe in TypeScript
Good: No extra work if the function has parameters
Bad: Derived classes can't call base class methods written this way using super.
Bad: The exact semantics of which methods are "pre-bound" and which aren't create an additional non-typesafe contract between your class and its consumers.
Function Expression at Reference Site
Shown here with some dummy parameters for explanatory reasons:
class DemonstrateScopingProblems {
private status = "blah";
public something() {
console.log(this.status);
}
public run(x: any, y: any) {
// OK
console.log(this.status + ': ' + x + ',' + y);
}
}
let d = new DemonstrateScopingProblems();
// With parameters
someCallback((n, m) => d.run(n, m));
// Without parameters
window.setTimeout(() => d.something(), 100);
Good/bad: Opposite memory/performance trade-off compared to the first method
Good: In TypeScript, this has 100% type safety
Good: Works in ECMAScript 3
Good: You only have to type the instance name once
Bad: You'll have to type the parameters twice
Bad: Doesn't easily work with variadic parameters
I think that you should move the result block into the subscribe callback associated the getPlaces method call:
showPosition(position) {
this.xml_Latitude = position.coords.latitude;
this.xml_Lang = position.coords.longitude;
this._http.getPlaces(this.xml_Latitude, this.xml_Lang).subscribe(
data => {
this.maps = data;
var result = this.maps.results; // <----------
var city = result[0].address_components[4].long_name + "," + result[0].address_components[6].long_name;
alert(city);
},
err => { this.cat_error = true }
);
}
It's because this.maps is undefined before the callback is called. And you try tyo get the result attribute before (this.maps.results).
Edit
I also see a problem at the line navigator.geolocation.getCurrentPosition. You could refactor your code this way:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => { // <----
this.showPosition(position);
});
} else {
alert("Geolocation is not supported by this browser.");
}

Cast route parameter in Nancy is always null

I have a Nancy module which uses a function which expects as parameters a string (a captured pattern from a route) and a method group. When trying to pass the parameter directly it will not compile as I "cannot use a method group as an argument to a dynamically dispatched operation".
I have created a second route which attempts to cast the dynamic to a string, but this always returns null.
using System;
using Nancy;
public class MyModule : NancyModule
{
public MyModule()
{
//Get["/path/{Name}/action"] = parameters =>
// {
// return MyMethod(parameters.Name, methodToBeCalled); // this does not compile
// };
Get["/path/{Name}/anotherAction"] = parameters =>
{
return MyMethod(parameters.Name as string, anotherMethodToBeCalled);
};
}
public Response MyMethod(string name, Func<int> doSomething)
{
doSomething();
return Response.AsText(string.Format("Hello {0}", name));
}
public int methodToBeCalled()
{
return -1;
}
public int anotherMethodToBeCalled()
{
return 1;
}
}
Tested with the following class in a separate project:
using System;
using Nancy;
using Nancy.Testing;
using NUnit.Framework;
[TestFixture]
public class MyModuleTest
{
Browser browser;
[SetUp]
public void SetUp()
{
browser = new Browser(with =>
{
with.Module<MyModule>();
with.EnableAutoRegistration();
});
}
[Test]
public void Can_Get_View()
{
// When
var result = browser.Get("/path/foobar/anotherAction", with => with.HttpRequest());
// Then
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
Assert.AreEqual("Hello foobar", result.Body.AsString()); //fails as parameters.Name is always null when cast to a string
}
}
You can find the whole test over on github
I've had similar issues when using 'as' so I tend to use explicitly cast it:
return MyMethod((string)parameters.Name, anotherMethodToBeCalled);
Also I think there was a bug raised with the casing on parameters, but I think it's better to keep them lowercase:
Get["/path/{name}/anotherAction"]
(string)parameters.name
Your code works for me with upper case and lowercase, using the explicit cast.

eclipse CDT Plugin development : How to get the class name which has a declaration

I'm developing an eclipse plugin based on CDT API.
Suppose I've following C++ code
class EventEnum
{
public:
enum e {
E_CompleteDisconnectSuccess = 1,
E_CreateBtAdapterNoSuccess = 2,
E_CreateBtAdapterSuccess = 3,
};
};
Using following ASTVisitor visitor method I can find the enum declaration
public int visit(IASTDeclaration declaration) {
if (declaration instanceof IASTSimpleDeclaration) {
IASTDeclSpecifier specifier = ((IASTSimpleDeclaration)declaration).getDeclSpecifier();
if (specifier instanceof IASTEnumerationSpecifier) {
IASTEnumerationSpecifier enumSpecifier = (IASTEnumerationSpecifier)specifier;
// Get the current enumeration name
String enumerationName = enumSpecifier.getName().toString();
System.out.println("Found enum : " + enumerationName);
}
}
return PROCESS_CONTINUE;
}
Question : How can I get the class name which contains the found enum declaration, in my case it will be EventEnum ?
Found the answer on my own, probably for someone it will be usefull, so I'm posting it here
if (enumSpecifier.getParent() instanceof CPPASTSimpleDeclaration)
{
if (enumSpecifier.getParent().getParent() instanceof CPPASTCompositeTypeSpecifier)
{
CPPASTCompositeTypeSpecifier firstLevelClass = (CPPASTCompositeTypeSpecifier)enumSpecifier.getParent().getParent();
return firstLevelClass.getName().toString();
}
}

How to get all visible variables for a certain method in JDT

I want to develop an Eclipse plug-in which get all visible variables for a specific method.
For example:
public class testVariable {
String test1;
Object test2;
void method_test1(){
int test3,test4;
}
void method_test2(){
int test5,test6;
//get variable here!!!!
}
}
I just want to get visible variable is: test1, test2,test5,test6 in method method_test2. What can I do?
Actually, JDT can be used outside of a plug-in, i.e., it can be used in a stand-alone Java application.
The following code can return the variables you want:
public static void parse(char[] str) {
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(str);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
final CompilationUnit cu = (CompilationUnit) parser.createAST(null);
cu.accept(new ASTVisitor() {
public boolean visit(VariableDeclarationFragment var) {
System.out.println("variable: " + var.getName());
return false;
}
public boolean visit(MethodDeclaration md) {
if (md.getName().toString().equals("method_test2")) {
md.accept(new ASTVisitor() {
public boolean visit(VariableDeclarationFragment fd) {
System.out.println("in method: " + fd);
return false;
}
});
}
return false;
}
});
}
The output is:
variable: test1
variable: test2
in method: test5
in method: test6
Check out more examples at JDT tutorials.