$PropertyType to get array entry - flowtype

I have a type def like this:
type Blah = {
fields: {
value: string
}[]
}
we see here fields is a bunch of array entries. I want to get that out via $PropertyType.
Doing $PropertyType<Blah, 'fields'> gives us the array, is it possible to get the element?
The reason I can't do type Field = {value:string} then type Blah = { fields:Field[] }is because I don't have control over typeBlah`, I am importing it from a 3rd party package.

You can use the new $ElementType utility to do this.
Try flow
type Blah = {
fields: {
value: string
}[]
}
type Fields = $PropertyType<Blah, 'fields'>
type Field = $ElementType<Fields, number>
const field: Field = {
value: 'blah'
}

Related

Presetting values for a type using Generics - Typescript

I know I'm way off track here but I'm trying to use generics to "preset" particular values of an "Event" type.
What I'm doing is as follows and what I'm expecting is "my-source" to be the console output.
I can see why this code doesn't work, but I'm putting it here to try and illustrate what I want to try and achieve.
type EventDetail = {
shopId: string;
};
export type Event<
TEventDetailType extends EventDetail,
TType extends string,
TSource extends string
> = {
source?: TSource;
body: TEventDetailType;
type?: TType;
};
export type UpdateShopCustomDomainEventDetail = EventDetail & {
domainName: string;
};
export type UpdateShopCustomDomainEvent = Event<
UpdateShopCustomDomainEventDetail,
"update-shop-custom-domain",
"my-source"
>;
const test:UpdateShopCustomDomainEvent = {body:{shopId:"123123", domainName:"asdf"}}
console.log(test.source);
// undefined
Essentially what I am wanting to do is something like the following. Where I send an event, but I define the type of event that I'm sending with a generic. This UpdateShopCustomDomainEvent will force the user to enter a value for shopId and domainName, and it will also set the type value to "update-shop-custom-domain" and the source to "my-source".
putEvent<UpdateShopCustomDomainEvent>({
body: {
shopId:"1234",
domainName:"mydomain.com"
}
});

Flow. How to specify the union type depending on the function argument

Let's say we have two types and union of them:
type A = {tag: 'a'};
type B = {tag: 'b'};
type U = A | B;
And function, which returns A or B, depending on provided tag:
const getSpecificObj = (tag: string) => U;
How can I specify that returning type? So then I will be able to use it like:
const a: A = getSpecificObj('a');
P.S. Yes, I know that I can write the same function for every type or override. But maybe there are another ways. For example in TS I can write:
type Extract<A, T> = A extends { tag: T } ? A : never;
<T>(tag: T): Extract<U, T>
Rather than returning a union of the types A and B, you need to parameterize the function getSpecificObj by the type of its argument, and then return an object which references that type parameter. Here's how I would do it:
type A = {tag: 'a'};
type B = {tag: 'b'};
function getSpecificObj<T : string>(tag: T) : { tag: T } {
return { tag };
}
const a : A = getSpecificObj('a');
const b : B = getSpecificObj('b');
The annotation <T : string> on getSpecificObj makes sure the function isn't more general than you need, and will only accept strings as tags. You can think of this as moving the string annotation off of the tag parameter and into the generic type of the tag parameter.
You can view the example on the try-flow page here.

How to transform a Custom Object List by excluding particular property in Kotlin?

How to transform a List into a new List by excluding a property in T.
For instance if User data class has 10 properties, I need to transform List into a new List without one particular property in User . New List like List
data class User(val name: String, val age: Int)
var userList = mutableListOf<User>()
var nameList= userList.map { it.name }
If a List to be created without property 'age'. Like
var withoutAgeList
In your first example:
var userList = mutableListOf<User>()
var nameList= userList.map { it.name }
The question "What's the type of nameList?" has a simple answer: List<String>. So let me ask you a similar question: What's the type of withoutAgeList? The answer to that question informs the answer to your question.
Perhaps a user without the age property is a separate AgelessUser class, meaning withoutAgeList is of type List<AgelessUser>. In that case, I suggest either a constructor or a factory function that builds AgelessUser from User, and you want one of these:
val withoutAgeList = userList.map { AgelessUser(it) } // constructor
val withoutAgeList = userList.map { agelessUserOf(it) } // factory
Alternatively, maybe the age property in User is nullable and immutable, and you want to represent users without an age as a regular User where age=null. In this case, you could copy the Users and override the age field
// TODO: pass all the other fields too
val withoutAgeList = userList.map { User(it.name, null) }
Assuming Users is a data class, we can avoid explicitly naming all fields by making use of copy():
val withoutAgeList = userList.map { it.copy(age = null) }
Maybe the age property is nullable and mutable — and you actually want to change the users in place instead of copying them. This is somewhat risky and I don't advocate doing it this way unless you really know what you're doing though.
userList.forEach { it.age = null }
// They're actually the same list!
val withoutAgeList = userList
In such a simple case you can map a list of Users into a list of strings:
val names: List<String> = userList.map(User::name)
Or you can declare a DTO and map into the latter:
class UserWithoutAge(val name: String)
val usersWithoutAge: List<UserWithoutAge> = userList.map { UserWithoutAge(it.name) }
P.S. you don't have to write an explicit type
You can use the Object Oriented approach:
data class User(val name: String, val age: Int)
data class UserNoAge(var name: String) {
constructor(user: User) : this(user.name)
}
var userList = listOf(User("John", 25), User("Jane", 30))
var userNoAge: List<UserNoAge> = mutableListOf<UserNoAge>()
userNoAge = userList.map{ UserNoAge(it) }
println(userNoAge) // [UserNoAge(name=John), UserNoAge(name=Jane)]

Bind repeater list with enum

I have a requirement where when a user clicks on image a list should be shown with checkboxes and all the categories that is present in DB and user should be able to select the checkboxes. How can this be achieved using asp:repeater control? the caegory is a enum type and can have n number of values. In repeater i have added a checkbox and a label; the label should display the category text.
To start with, you should add the [Description] attribute to each value in your Enum. This allows you to set proper descriptive text for each value. This attribute is in System.ComponentModel, here's an example: -
public enum CalendarShowAsEnum
{
[Description("None")]
None = 10,
[Description("Busy")]
Busy = 20,
[Description("Out Of Office")]
OutOfOffice = 30,
[Description("On Holiday")]
OnHoliday = 40
}
You then need 2 functions: -
One function that takes an Enum type and a ListBox/DropDown as parameters, and adds an entry for each Enum into the list
A helper function that converts the enum into the descriptive title you gave them (example above)
The List function might look as follows (all this is taken from a project I worked on): -
public static void BindNamedEnumList(ListControl list,
Type enumerationType)
{
list.Items.Clear();
Array array = Enum.GetValues(enumerationType);
ListItem item;
string name;
var enumerator = array.GetEnumerator();
if (enumerator != null)
{
while (enumerator.MoveNext())
{
Enum value = enumerator.Current as Enum;
name = EnumHelper.GetEnumName(value);
item = new ListItem(name);
item.Value = Convert.ToInt32(value).ToString();
list.Items.Add(item);
}
}
}
This function takes a Type and a ListControl (which ListBox and DropDownList both inherit from). The Type is the .GetType() of the enum you want to add to the list. Note that it doesn't select any values and that it does depend on each enum value having a defined integer value. The latter part will help you with selecting individual items.
Note the loop calls EnumHelper.GetEnumName(value) - this is the helper function that uses the Description attribute I mentioned at the start. This function looks like: -
public static string GetEnumName(object value)
{
string retVal = string.Empty;
try
{
FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
retVal = ((attributes.Length != 0) ? attributes[0].Description : value.ToString());
}
catch (System.NullReferenceException)
{
}
finally
{
if (string.IsNullOrEmpty(retVal))
{
retVal = "Unknown";
}
}
return retVal;
}
It uses reflection, so you'll need to add an Imports for System.Reflection
To use the list function to bind a set of Enum values to the list, simply call
{HelperClass}.BindNamedEnumList(myListBox, typeof({MyEnumType})

Question about using Anonymous List Types

private List<T> GetFieldList()
{
var Fields = new { DisplayName = "MCP", FieldName = "t.MCP", FieldType = 1 };
var FieldList = (new[] { Fields }).ToList();
return FieldList;
}
Should I be able to do something like this?
If I understand correctly your tag "asp.net" this construction will be used as part of data binding.
Just use non generic :
private IList GetFieldList()
{
var Fields = new { DisplayName = "MCP", FieldName = "t.MCP", FieldType = 1 };
IList FieldList = (new[] { Fields }).ToList();
return FieldList;
}
It would be nice handled by all data-bound controls.
I just realized I don't need to use an anonymous list as I know the structure of the data I'm expecting, so I'll just create a small class for it.

Resources