Capitalized field name in record - javascript-objects

Is it possible to make a record with a capitalized field name?
something like:
[#bs.deriving jsConverter]
type coordinates = {
X: int,
Y: int
};
The reason I ask is because the js object I'm interfacing with has capitalized keys.
Here's the link to converting record to bucklescript js object:
https://bucklescript.github.io/docs/en/generate-converters-accessors.html#convert-between-jst-object-and-record

You can prefix the fields with an underscore, which will be removed in the generated JS:
[#bs.deriving jsConverter]
type coordinates = {
_X: int,
_Y: int
};
Documentation
That said, I'm not sure it's such a good idea to rely on jsConverter for JS interop, since its pretty limited and not generalizable. And while this mangling happens to work here too, it seems like more of a coincidence.

Related

Why does passing the plot type ('scatter', 'bar', etc.) as string variable does not work? (using <Plot ... /> from react-plotly.js)

I am using TypeScript, React and Plotly in my project and would like to know if it is possible to pass the plot type specification using a variable. Something like this (which is not a working code example and only used to indicate what I mean)
import Plot from 'react-plotly.js';
var plotType: string = 'bar';
return (
<Plot
data={[{
x: [1,2,3,4],
y: [1,2,3,4],
type: 'bar' // this works
type: plotType // this doesn't
}]}
/>
);
It's not really an issue since I go about the whole 'data' thing using a state property, but I still don't get why it works with the literal string but not with a variable.
The error is something like 'string' cannot be assigned since '"bar"|"scatter"|"line" ...' is expected.
For a working example I can only refer to the react-plotly github repos, where one can use the given quickstart example and try to substitute the string in type: 'scatter' with a variable.
PS.: I am quiet new to TS or JS in general so I might be using wrong/misleading terms unknowningly.
It isnt entirely evident in their docs but, this is actually a TS feature that the plotly devs are using.
I can say
type MyType = string;
then if I say
const myVar = '123';
TS will be perfectly happy. On the other hand, I could restrict other devs on what actual values they assign to MyType like
type MyType = 'bar' | 'pie' | 'scatter';
which is exactly what plotly has done. and then if a dev says
<Plot type={'123'} />
TS will throw an error because '123' isnt one of the options.
Now, you say, but my plotType variable IS one of those options. While thats true, you typed it as :string. So, when TS type checks is compares the PlotType type inside Plotly which is a limited set of strings to the string type. Thus, you have a mismatched type. In your case you could have said
var plotType: Plotly.PlotType = 'bar';
since the types now match, this would be acceptable. In fact, in this case you wouldnt even be able to accidently change the value of plotType to something not a part of Plotly.PlotType because TS would complain now.

Swift Array multiple appending on click

I'm creating a button that when clicked adds the current date and time to an array but when I try to append to the array it only appends once and not repeating the process
the Entries struct:
struct Enteries {
var dates:[String] = []
}
convert date to String:
func DateConverter(){
format.timeZone = .current
format.dateFormat = "yyyy-MM-dd HH:mm"
dateString = format.string(from: currentDate)
}
The function that appends: also its called later whenever an IBAction is triggered
func AddToDatabase () {
var entery = Enteries()
entery.dates.append(dateString)
print(entery.dates)
}
`
Yikes, there's a lot going on here.
First of all, Swift's convention is to use lowerCamelCase for functions. Only type names should be UpperCamelCase.
Secondly, function names should be verbs or verb phrases, type names should be nouns. If I saw DateConverter in some code, I would expect it to be a type. It's an UpperCamelCase noun, that's how types should be named. But yours is a function (which would be a total surprise to every other Swift developer, because it violates the expectations they've built up from Swift's naming conventions), that function should probably be called parseDate.
Which way does DateConverter convert? From String to Date, Date to String, or both? What's its input? What's it's output? These things should be obvious from a good function name, but are totally unknown here without looking at the implementation.
Critically, the DateConverter function doesn't take input from parameters, and doesn't return a result, instead it takes input from a side effect (accessing the variable currentDate) and returns a result via side effect (writing to an a variable dateString). This is really bad, for several reasons:
It's not reusable. You have no way to use this date parsing code somewhere else without copy/pasting it, which is how code duplication and complexity arise. If you ever decide to change the date format in your app, you won't have a central source-of-truth that you can change, instead you'll have to manually hunt down every copy of this function, and change it, hoping you don't miss any. Not good.
It's not thread safe
It's more complex than a simple function that has type (Date) -> String. It obfuscates what's going on.
It defies peoples' expectations, without justification.
Enteries.dates has a default value of [], which doesn't seem to be a good idea if you're going to be appending to it as soon as you create it. Instead, take the array via an initializer parameter.
Enteries.dates has type [String]. Why?! You already have Date objects, store those!
They're smaller (in memory)
They're presentation-agnostic, meaning you can properly format them for different interfaces and different locales at a later time, as necessary
They support date math. I often see people storing dates as strings, and ask questions like "How do I sort my array of dates?" (which are actually stored as strings), "How do I add 1 day to "2019-12-24", and they start doing funky parsing, splitting, joining, and it's all just an absolute mess
Here's how I would improve this code:
struct Entries {
var entries: [Entry]
}
struct Entry {
let date: Date
}
// Call this from your view layer, only when you're about to present a `Date` to a user.
func parse(date: Date) -> String {
let df = DateFormatter()
df.timeZone = .current
df.dateFormat = "yyyy-MM-dd HH:mm"
return format.string(from: currentDate)
}
var entries = Entries(entries: [])
func addToDatabase(entry: Entry) {
entries.append(entry)
print(enteries.entries)
}
you are creating a new entery object eveytime the function is called. SO its creating a new object everytime. Declare your entery object outside the function.
var entery = Enteries()
func AddToDatabase () {
entery.dates.append(dateString)
print(entery.dates)
}

Is there any way to handle Google Datastore Kind Property names with spaces in Golang?

I'm running in a nasty issue with Datastore that doesn't appear to have any workaround.
I'm using the Google Appengine Datastore package to pull back projection query results into Appengine memory for manipulation, and that is being accomplished with representing each entity as a Struct, with each Struct field corresponding to a Property name, like so:
type Row struct {
Prop1 string
Prop2 int
}
This works great, but I've extended my queries into reading other property names that have spaces. While the query runs fine, it can't pull the data back into structs as it's looking to place the given value into a struct of the same naming convention, and I'm getting this kind of error:
datastore: cannot load field "Viewed Registration Page" into a "main.Row": no such struct field
Obviously Golang cannot represent a struct field like this. There is a field of the relevant type but no obvious way to tell the query to place it there.
What would be the best solution here?
Cheers
Actually Go supports mapping entity property names to different struct field names using tags (see this answer for details: What are the use(s) for tags in Go?).
For example:
type Row struct {
Prop1 string `datastore:"Prop1InDs"`
Prop2 int `datastore:"p2"`
}
But the Go implementation of the datastore package panics if you attempt to use a property name which contains a space.
To sum it up: you can't map property names having spaces to struct fields in Go (this is an implementation restriction which may change in the future).
But the good news is that you can still load these entities, just not into struct values.
You may load them into a variable of type datastore.PropertyList. datastore.PropertyList is basically a slice of datastore.Property, where Property is a struct which holds the name of the property, its value and other info.
This is how it can be done:
k := datastore.NewKey(ctx, "YourEntityName", "", 1, nil) // Create the key
e := datastore.PropertyList{}
if err := datastore.Get(ctx, k, &e); err != nil {
panic(err) // Handle error
}
// Now e holds your entity, let's list all its properties.
// PropertyList is a slice, so we can simply "range" over it:
for _, p := range e {
ctx.Infof("Property %q = %q", p.Name, p.Value)
}
If your entity has a property "Have space" with value "the_value", you will see for example:
2016-05-05 18:33:47,372 INFO: Property "Have space" = "the_value"
Note that you could implement the datastore.PropertyLoadSaver type on your struct and handle this under the hood, so basically you could still load such entities into struct values, but you have to implement this yourself.
But fight for entity names and property names to not have spaces. You will make your life harder and miserable if you allow these.
All programming languages that I know treat a space as the end of a variable/constant name. The obvious solution is to avoid using spaces in property names.
I would also note that a property name becomes a part of every entity and every index entry. I don't know if Google somehow compresses them, but I tend to use short property names in any case.
You can use annotations to rename properties.
From the docs:
// A and B are renamed to a and b.
// A, C and J are not indexed.
// D's tag is equivalent to having no tag at all (E).
// I is ignored entirely by the datastore.
// J has tag information for both the datastore and json packages.
type TaggedStruct struct {
A int `datastore:"a,noindex"`
B int `datastore:"b"`
C int `datastore:",noindex"`
D int `datastore:""`
E int
I int `datastore:"-"`
J int `datastore:",noindex" json:"j"`
}

can we edit the definitely typed file in typescript to change some parameter types?

Can we edit definitely typed file in Typescript?
When using ui-grid with typescript I came across a scenario where I edited the
ui-grid.d.ts file to make the date filter work. I need to filter the date based on the displayed result in the ui-grid and not on the
raw data (the data which I am getting from the Web API).
Here is the code snippet:
ui-grid.d.ts file code:(under interface IFilterOptions)
condition?: number;
Corresponding typescript code:
column.filter = {
condition: (searchTerm, cellValue, row, column) => {
var date = this.$filter("date")(row.entity.Date, this.masks.date.angular)
return (date + '').toLowerCase().indexOf(searchTerm.toLowerCase().replace(/\\/g, "")) !== -1;
}
}
The error I faced is as follows:
Type '(searchTerm:any, cellValue:any, row:any, coloumn:any) => boolean' is not assignable to type 'number'
After that I made the changes to the filter object to return a number as follows:
column.filter = {
condition: (searchTerm, cellValue, row, column) => {
var date = this.$filter("date")(row.entity.Date, this.masks.date.angular)
var res: number = (date + '').toLowerCase().indexOf(searchTerm.toLowerCase().replace(/\\/g, "")) !== -1 ? 1 : 0;
return res;
}
}
But after this I got error saying that:
Type '(searchTerm:any, cellValue:any, row:any, coloumn:any) => number' is not assignable to type 'number'
After this I made the change in the definitely typed file i.e. in the ui-grid.d.ts file as follows:
under interface IFilterOptions
I changed
condition?: number;
to
condition?: (searchTerm: any, cellValue: any, row: any, column: any) => boolean | number;
so the corresponding filter function which worked for me is as follows:
column.filter = {
condition: (searchTerm, cellValue, row, column) => {
var date = this.$filter("date")(row.entity.Date, this.masks.date.angular)
return (date + '').toLowerCase().indexOf(searchTerm.toLowerCase().replace(/\\/g, "")) !== -1;
}
}
Is this the right way to solve this problem?
Can anyone guide me to the right solution if the above solution is not good or it is not a good practice to edit the definitely typed file?
And also used
column.filterCellFiltered = true;
instead of filter function but it didn't work. This is also a concern as why it didn't work because I need to filter the date based on the displayed result in the ui-grid and not on the raw data. Can anyone explain why it didn't work?
Please help me understand the right approach. Let me know if anyone require any other details. Thanks in advance.
Angular JS version: AngularJS v1.4.7
Angular JS definitely typed version : Angular JS 1.4+
ui-grid Version: * ui-grid - v3.0.5
ui-grid definitely typed version: ui-grid v3.0.3
typescript version: 1.0.3.0
i had also same problem ,
adding "< any >" beginning of the function should solve the problem.
like this :
condition: <any>((searchTerm, cellValue, row, column) =>
{
return cellValue.indexOf(searchTerm) > -1
})
and don't forget to parenthesis ().
You can, but the changes will be overwritten the next time you install/upgrade that dependency, and won't be reflected in git (assuming you're not checking generated files into source control). You're better off overriding the type definitions in your project. The common way to do this is within an #types directory but anywhere within your TS project will work.
You'll want to create a file with the extension .d.ts under TS's project files. The modules within this file will be merged with other declaration files, to determine the final type definition. So in your case you'd want:
// ui-grid.override.d.ts
declare module 'ui-grid' {
// overriden types go here
}
The benefit of this method is that you only need to add the types you want, and the rest will be merged with the definitely typed declarations.
This is a very useful tool if you need to do things like type globals, or to provide additional type information for libraries. It's used extensively in the definitely typed declarations for library plugins which alter an api in some way.
I'd recommend reading the TS docs on declaration files as they're an incredibly useful tool if used correctly.
Although if you do find the types in definitely typed are incorrect/incomplete then please create a PR for the benefit of everyone
I do not recommend to modify definitions and sources of the libraries you do not actively develop. What will happen when you will decide to upgrade to the newer version and it will override your changes? You will be forced to merge them each time you upgrade. And the larger your project will get the more complicated this will become.
I would recommend to either submit a request to the angular-ui team, or find a way to go with existing functionality.
Hope this helps.

BreezeJS: Change Enum Text Values in MetadataStore

I'm absolutely loving BreezeJS and was so surprised to see that my Enum values were being displayed as their text values and not their ordinal ones! What I would love to be able to do is, on the client side, open the MetadataStore, fetch the enumeration and modify it's textual properties for display purposes.
Is this currently possible? From my research it would appear not, but I'm wondering if there is perhaps a simple workaround. Everything I've tried has involved a large number of hacks and server-side attributes, but to no avail, or the solution just seemed overly complex and not worth the benefits.
Here is what I said about how to get the enum values from raw metadata in another SO comment.
The enum values are available in the metadata generated by EF and sent to a Breeze client. I agree Breeze should pick them up automatically and put them somewhere so you don't have to make a separate request for them or extract them from the raw metadata passed to the MetadataStore.fetchMetadata success callback. It's on our backlog.
Meanwhile, you'll have to get them by hand. There is a DocCode test that shows how:
/*********************************************************
* Can can get enum types from raw EF-generated metadata
* Related to feature request #2271: Extract enum values from server metadata
*************************************************************/
asyncTest("can get enum type from raw EF-generated metadata", function() {
var serviceName = testFns.foosMetadataServiceName;
var store = new breeze.MetadataStore();
store.fetchMetadata(serviceName)
.then(metaSuccess, metaFail).fail(handleFail).fin(start);
function metaSuccess(rawMetadata) {
ok(true, "foos metadata fetched");
var enumType = rawMetadata.schema && rawMetadata.schema.enumType;
if (enumType && enumType.name ==='Color') {
var members = enumType.member;
ok(members.length,
"should have several members; members are: " + JSON.stringify(members));
} else {
ok(false, "metadata should have had one enumType, 'Color'.");
}
}
function metaFail(error) {
ok(false, "foos metadata fetch failed: " + error.message);
}
});
we're using Breeze with NHibernate and wand to do the same. Metadata generated for NHibernate are standard breeze Metadata and doesn't contain the Schema part. Any ideas how to do it?
edit: To fix our issue I added a list of all used enums in the metadata(like the structuralTypes node). Then we cache it on the client when the metadata are retrieved.
https://github.com/lnu/breeze.server.net/commit/65ad687ad13c4dd9f4a6ab6a3ed09e407e2b58ec
Thanks

Resources