How to allow assignment of incompatible Typescript types? - mongodb

I'm sharing type definitions between my server and front-end. They're defined in a separate npm package that both install. On the front-end, variables holding ObjectIds need to be typed as that but, on the client, I can assume they're always primitive strings.
I've got a number of places on the client that throw:
Type 'ObjectId' is not assignable to type 'string'.
What's the easiest way to deal with this error? Can I tell Typescript to accept string assignment to ObjectId and vice versa on the client? Should I be trying to override the Mongoose definition of ObjectId?
I'm considering an override of the sort
declare global {
export interface MyInterface1 {
variableWithObjectId1: string
}
export interface MyInterface2 {
variableWithObjectId2: string
}
}
I think this is supposed to work. It's the recommended solution for a similar issue but I have yet to make that work.
I'm hoping there is some way to globally transform ObjectId to string when the library is imported into the client.

ObjectId and String are not the same types at all, hence you cannot simply assign from one to the other.
You need to perform proper conversions.

For each of these errors on the client, I'm converting the type to a string like
var stringId = (myVariable as unknown) as string
I wish there was a cleaner way than this so I'm all ears if someone has a suggestion.

Related

How do I access an object field via its field name in string form?

I'm figuring out at compile-time the name of a specific field of an object that I want to access. Before I compile, I do not necessarily know which field that is going to be, so I just have that field name as a string. How can I leverage nim's metaprogramming to access that field on the object?
You can write a very simple macro that evaluates to a dot expression (aka object.yourFieldNameString).
Here an example of how that can look like:
import std/[macros]
macro getField*(obj: object, fieldName: static string): untyped =
nnkDotExpr.newTree(obj, ident(fieldName))
This will only work if you know the field at compiletime (aka when you have it as a static string)! Keep that in mind!

Generic ViewModel in Swift

I'm following the MVVM pattern in my app. As a result I have a bunch of classes which virtually consist of the same code: fetch some data from an SQL server, save some data to an SQL server. This does not seem to be the most efficient way to do this, so I thought I should just generalise
the code down to a single SQLViewModel class which takes in any type of data model object. Right now it looks promising, though a couple of things are still causing weird behaviour, e.g. for some reason
var json = [T]()
doesn't cause any compiler warnings, while
var json = T()
stops with an Missing argument for parameter 'from' in call. Insert 'from: <#Decoder#>' error. My real question though is this: Is this actually a good way to simplify the code or will this cause me many more issues at a later time? Would it maybe be better to stick with the one model one viewmodel pattern and for instance use an extension for each viewmodel which hosts the shared code?
Thanks for any insights!
Missing argument for parameter 'from' in call. Insert 'from: <#Decoder#>'
Seems like the compiler complains because it can't find init(from:) in T
Which means that your generic declaration is missing a constraint eg.:
class MyClass<T: Decodable> {
// ...
}
Without more details I can say much more than that

How to declare and init nested enum with reserved keyword as type name in Swift?

I'm having a hard time to figure out how to declare a certain nested enum and calling one of it's automatic constructors. This enum i'm trying to declare is supposed to have a reserved keyword as type name.
Here is a simplified example of what i'm trying to do:
import Foundation
public class Foo {}
public extension Foo {
enum `Type`: Int {
case bar
}
}
var type: Foo.`Type`
type = Foo.`Type`(rawValue: 0)
This doesn't compile in Swift 5.2 with error
error: type 'Foo.Type' has no member 'init'
I'm pretty sure it is just a matter of getting the syntax right but i just can't figure it out. Anyone can please explain how to do it or is it just impossible all together?
There is no way to do this specific thing you want to do. That's why nobody uses nested types named Type, even though we all want to—the language already provides this type, and you don't get to override it with your own. We all use the Objective-C style naming of just smashing the word Type right up there without a proper delimiter.
FooType is what you've got to work with.

How everyone manage their firestore paths?

I am using cloud function and client access firestore.but all paths string are hardcode in code. once I changed a collection name I need to change everywhere that the code access same collection. Anyone have a better way to manage them?
Instead of literal strings everywhere, declare a global constant. For example, the usual thing in Swift is a struct or enum with a constant static property.
struct Constants {
static let key = "whatever"
}
Now you can say Constants.key anywhere in your program. Any computer language will have something equivalent.

Swift keyPath vs protocol

I understand the basic idea of keyPaths but I do not understand its use cases. If you already know the type of the instance, you can access their properties easily. If you don’t, protocol already supports read-only, read-write properties. Can someone explain me what I am missing? Anything that we can’t do with protocols but keyPaths or when keypaths are better than protocols?
If you already know the type of the instance, you can access their properties easily. If you don’t, protocol already supports read-only, read-write properties. Can someone explain me what I am missing?
What you're missing is a sense of what's unknown.
In both your sentences you speak of knowing what the instance's properties are. That's not the problem key paths solve. Key paths have nothing to do with knowing the type; they are not in any kind of opposition to types or protocols. On the contrary, before you can use a key path, you have to know exactly what the instance's properties are.
Key paths are for when what is unknown is which property to access. They provide a way to pass a property reference so that someone else can be told to access that property.
For example, here's a Person type:
struct Person {
let firstName : String
let lastName : String
}
And here is a function that sorts an array of Persons by either the firstName or the lastName, without knowing which one to sort by:
func sortArrayOfPersons(_ arr:[Person], by prop: KeyPath<Person, String>) -> [Person] {
return arr.sorted { $0[keyPath:prop] < $1[keyPath:prop] }
}
A key path is how you tell this function what property to use as a basis for sorting.