Define interface variable with only two string hardcoded values - interface

I have the following code:
interface ResponseFromServer {
type:string;
message:string;
}
How can I restrict the type variable for being only one of the two following values:
"success"
"error"

The answer from 2013 is now deprecated.
It is now possible in this way:
interface ResponseFromServer {
type: "success" | "error";
message: string;
}

This isn't possible. Types are about the shape of the data, not the content.

Related

#PathParam: No value being passed

I'm building a REST api using Quarkus and Kotlin. I'm trying to include a path parameter in my function by using the #PathParam annotation. This is what I have:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/{userId}")
fun getUser(#PathParam userId: UUID) : GetUserResponse =
try {
GetUserSuccess(userRepository.find("id", userId))
} catch (e: NotFoundException) {
GetUserFailure(e)
}
Unfortunately I'm getting an error stating that there's no value being passed for parameter value.
I googled some stuff, and most of what I found is about wrong imports. I double checked that part, but I import the correct one: import javax.ws.rs.*, which also includes the PathParam.
Anyone knows what's wrong with this?
The answer would be to change it to:
fun getUser(#PathParam("userId") userId : UUID)
Inspirerd by Paul Samsotha's answer.
Alternatively you could also use the #RestPath annotation from RESTEasy:
fun getUser(#RestPath userId: UUID)

Rescript Record: Key as Array

In Rescript, one can define a Record in this format:
type record1 = {
a : String
}
but NOT:
type record2 = {
[a] : String
}
I am looking to write a record that compiles to JS like:
{
[Op.or]: [12,13]
}
The use case above comes from Sequelize, and the reference is here.
My current solution:
%raw(`{[Op.or]:[12,13]}`)
It's not entirely clear how you intend to interface with the Op construct, whether you can bind to it or not, but here's an example that does, and along with Js.Dict.t effectively produces the same output:
module Op = {
#val external or: string = "Op.or"
}
Js.Dict.fromList(list{
(Op.or, [12, 23])
})
It does not directly compile to the JS you want, however, which might be a problem if you rely on something that actually parses the source code. But short of that, I believe this should do what you ask for.

AWS-CDK Appsync Codefirst input types

To avoid duplication of data structures I wanted to reuse a type definition on an input type like this
export const DeviceStatus = new ObjectType('DeviceStatus', {
definition: {
time: timestamp,
firmwareVersion: string
},
});
export const DeviceStatusInput = new InputType('DeviceStatusInput', {
definition: {
tenantId: id_required,
deviceId: id_required,
// Reuse of DeviceStatus Field definition
status: DeviceStatus.attribute()
}
});
There is no error since the return type of DeviceStatus.attribute() is fine, and this works for ObjectType inheritance.
From my perspective this should work, but deploying results in a nasty "Internal Error creating Schema" error.
Of course I could move the whole definition into an object and reuse it but that seems weird. Is there any good solution on this for the CodeFirst approach
It seem to be invalid to reference object type in input type.
I recommend to view Can you make a graphql type both an input and output type?
Probably best you can do is to create some convenience method which will create you both object and input type from single definition.

Using local variables in function built with haxe macro

I have a LangBuilder macro class; it's used to build a langObjects:Map<String, Dynamic> of texts in various languages at compile time, and inject this structure in classes via #:build macro. Every item of the Map has a field for every language supported. So the result is:
#:build(LangBuilder.build())
class Lang{}
trace(Lang.langObjects["hello-world"].en); //outputs "Hello World!"
trace(Lang.langObjects["hello-world"].it); //outputs "Ciao Mondo!"
This works perfectly, but I thought I could make a cleaner job hiding the langObjects structure using a function getLangText with arguments the id of the text (e.g. "hello-world") and the language code (e.g. "it").
So I'm trying to add this function to classes:
public static function getLangText(id:String, lang:String)
Its non-macro version could be expressed as:
public static function getLangText(id:String, lang:String){
var _langObj_id = langObjects[id];
switch(lang){
case "it":
return _langObj_id.it;
case "en":
return _langObj_id.en;
}
return "Missing Translation";
If i translate this function as a macro with this code:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
switch($i{"lang"}){
case "it":
return _langObj_id.it;
case "en":
return _langObj_id.en;
}
return "Missing translation";
};
var myFunc:Function = {
args: [{
name: "id",
type: TPath({name: "String", pack: []}),
meta: null
},
{
name: "lang",
type: TPath({name: "String", pack: []}),
meta: null
}],
ret: (macro:String),
expr: macro $code
};
fields.push({
pos: Context.currentPos(),
name: "getLangText",
meta: null,
kind: FieldType.FFun(myFunc),
doc: null,
access: [Access.APublic, Access.AStatic]
});
... it works without problems. However I would like to know how it could be written without the switch, to make it more flexible and to learn something about haxe macros. I have seen some examples where fields could be accessed in macros with $p{} or with object.$fieldName. However the haxe manual warns that the second form could be used only for simple identifiers; for example object.${fieldName} would not work.
So I try this code:
var code = macro {
var l:String = $i{"lang"};
var _langObj_id = langObjects[$i{"id"}];
return _langObj_id.$l;
};
The compiler gives an error
Unknown identifier : l
on the line containing return _langObj_id.$l;.
Then i tried to use the $p{} reification:
var code = macro {
var _langObj_id = langObjects[$i{"id"}];
return macro $p{["_langObj_id", $i{"lang"}]};
};
But the error is similar:
Unknown identifier : lang
I can surely change the langObjects structure to Map<String, Map<String, String>> and then change the code to:
var code = macro {
return macro langObjects[$i{"id"}][$i{"lang"}];
};
I think this would work, but now i'm trying to understand why both _langObj_id.$lang and $p{["_langObj_id", $i{"lang"}]} wouldn't work, and what would be the correct way to access a field in a situation like that.
The value of the lang parameter is not known at compile- / macro-time, so I don't see how you could generate a field access expression like langObjects["mytext"].en. At runtime when getLangText() is actually called, lang could be "en", or anything else. So that would still require a switch-case, if-else-chain or reflection to handle all the possible values.
If instead of using being created by a build macro, getLangText() was an expression macro / a macro function, the function call would be evaluated at compile-time, and be replaced with the expression it returns. That would allow you to generate the appropriate field access expression based on the parameters. It could look something like this:
class Macro {
public static var langObjects = ["mytext" => {en: "hello", de: "hallo"}];
public static macro function getLangText(id:String, lang:String) {
return macro {
var langObject = Macro.langObjects[$v{id}];
langObject.$lang;
}
}
}
class Main {
static function main() {
trace(Macro.getLangText("mytext", "en"));
trace(Macro.getLangText("mytext", "de"));
}
}
Compiles to the following on the JS target:
Main.main = function() {
var langObject = Macro.langObjects.get("mytext");
console.log("source/Main.hx:3:",langObject.en);
var langObject1 = Macro.langObjects.get("mytext");
console.log("source/Main.hx:4:",langObject1.de);
};
Perhaps that's what you're looking for? Hard to say without knowing what problem you're trying to solve.

Does Typescript support "subset types"?

Let's say I have an interface:
interface IUser {
email: string;
id: number;
phone: string;
};
Then I have a function that expects a subset (or complete match) of that type. Maybe it will pass an entire object, maybe it will just pass in {email: "t#g.com"}. I want the type checker to allow for both.
Example:
function updateUser(user: IUser) {
// Update a "subset" of user attributes:
$http.put("/users/update", user);
}
Does Typescript support this sort of behavior yet? I could find it very useful, particularly with paradigms like Redux.
To clarify, the goal is:
Avoid re-writing an interface and manually setting all attributes to optional.
Avoid assignment of unexpected attributes (such as spelling mistakes).
Avoid imperative logic such as if statements, which forfeit benefits of compile time type checking.
UPDATE: Typescript has announced support for mapped types which should solve this problem once published.
It's worth noting that Partial<T>, as suggested in the accepted answer, makes all fields optional, which is not necessarily what you need.
If you want to make some fields required (e.g. id and email), you need to combine it with Pick:
type UserWithOptionalPhone = Pick<IUser, 'id' | 'email'> & Partial<IUser>
Some explanation:
What Pick does is that it lets you specify a subset of the interface succinctly (without creating a whole new interface repeating the field types, as suggested by other answers), and then lets you use those, and only those fields.
function hello1(user: Pick<IUser, 'id' | 'email'>) {
}
hello1({email: '#', id: 1}); //OK
hello1({email: '#'}); //Not OK, id missing
hello1({email: '#', id: 1, phone: '123'}); //Not OK, phone not allowed
Now, this is not exactly what we need, as we want to allow, but not require phone. To do that, we "merge" the partial and the "picked" version of our type by creating an intersection type, which then will have id and email as required fields, and everything else as optional – exactly how we wanted it.
function hello2(user: Pick<IUser, 'id' | 'email'> & Partial<IUser>) {
}
hello2({email: '#', id: 1}); //OK
hello2({email: '#', id: 1, phone: '123'}); //OK
hello2({email: '#'}); //Not OK, id missing
Typescript now supports partial types.
The correct way to create a partial type is:
type PartialUser = Partial<IUser>;
What you want is this
type Subset<T extends U, U> = U;
this makes sure, that U is a subset of T and returns U as a new type. for example:
interface Foo {
name: string;
age: number;
}
type Bar = Subset<Foo, {
name: string;
}>;
you can not add new properties to Bar which are not part of Foo - and you can not alter types in a non-compatible way. this also works recursively on nested objects.
proper solution with mapped types:
updateUser<K extends keyof IUser>(userData: {[P in K]: IUser[P]}) {
...
}
You can declare some or all fields as optional fields.
interface IUser {
email: string; // not optional
id?: number; // optional
phone?: string; // optional
};
You can seperate it into different interfaces:
interface IUser {
id: number;
};
interface IUserEmail extends IUser {
email: string;
}
interface IUserPhone extends IUser {
phone: string;
}
Have your method receive the base IUser interface and then check for the fields you need:
function doit(user: IUser) {
if (user.email) {
} else if (user.phone) {
}
}
If I understand this question correctly, you want something like Flow's $Shape
So, in one place, you may have something that requires the type
interface IUser {
email: string;
id: number;
phone: string;
};
Then, in another place you want a the type with the same type as IUser just with all the fields now optional.
interface IUserOptional {
email?: string;
id?: number;
phone?: string;
};
You want a way to auto-generate IUserOptional based on IUser without having to write out the types again.
Now, I don't think this is possible in Typescript. Things may change in 2.0, but I don't think we're even close to something like this in Typescript yet.
You could look at a pre-compiler which would generate such code for you before typescript runs, but that doesn't sound like a trivial thing to do.
With this problem in mind, I can only suggest you try Flow instead. In flow you can just do $Shape<IUser> to generate the type you want programmatically. Of course, Flow differs from Typescript in many big and small ways, so keep that in mind. Flow is not a compiler, so you won't get things like Enums and class implementing interfactes