I have a method which returns an object (this._response) which is of type IResponse. I want to return this._response.details which is of type IDetails.
get response(): IResponse {
if (this._response.response.header.statusCode === "0000" || this._response.response.header.statusCode === "YHOO") {
return this._response.details; //IDetails
} else if (this._response.response.header.statusCode === "6621" || this._response.response.header.statusCode === "6622") {
this._response.response.isViewError = true;
} else {
this._response.response.showError = this._response.response.header;
}
return this._response //IResponse
}
[ts] Property 'details' does not exist on type 'IResponse'.
How can I return different types from method based on if condition?
You can use union types:
get response(): IDetails | IResponse {
...
}
Edit
The problem with returning a union is that you'll need to check for the type of the result every time you invoke the function.
So:
function isResponse(obj: IDetails | IResponse) obj is IResponse {
return obj && obj.response;
}
let value = myObj.response;
if (isResponse(value)) {
// value is IResponse
} else {
// value is IDetails
}
Another option is to simply not specify anything; the return types are automatically inferred:
the danger here is this allows you to return anything so there is no explicit guard, during development, against wrong return types.
Related
I'm trying to use dynamic includes but I have problem to manage output files:
/*
* enables modules
*/
nextflow.enable.dsl = 2
include { requestData } from './modules/get_xapi_data'
include { uniqueActors } from './modules/unique_actors'
include { compileJson } from './modules/unique_actors'
if (params.user_algo) {
include { userAlgo } from params.user_algo
}
workflow {
dataChannel = Channel.from("xapi_data.json")
requestData(dataChannel)
uniqueActors(requestData.out.channel_data)
if (params.user_algo) {
user_algo = userAlgo(requestData.out.channel_data)
} else {
user_algo = null
}
output_json = [user_algo, uniqueActors.out]
// Filter output
Channel.fromList(output_json)
.filter{ it != null } <--- problem here
.map{ file(it) }
.set{jsonFiles}
compileJson(jsonFiles)
}
The problem is userAlgo can be dynamically loaded. And I don't know how I can take care of it. With this solution, I got a Unknown method invocation getFileSystem on ChannelOut type error.
The problem is that fromList expects a list of values, not a list of channels. If you use an empty Channel instead of checking for a null value, you could use:
if( params.user_algo ) {
user_algo = userAlgo(requestData.out.channel_data)
} else {
user_algo = Channel.empty()
}
user_algo
| concat( uniqueActors.out )
| map { file(it) }
| compileJson
I have a list of states, which are defined to be ordered by min to max. the sequence is the following:
Cancelled - complete - draft - reservation - reserved - ordered - confirmed
So the cancelled is the minimum state, and confirmed is the maximum state. I may have different instances with different states, so I use a for-each loop to run through all states, and select the minimum state present in the loop.
That is: if in a list I have states [complete, reserved, draft, ordered] I need to check all the values and select complete -as it appears to be the minimum state. OR
if I have [reserved, confirmed, ordered, draft, cancelled, confirmed, confirmed] I need to select the cancelled value, as it appears to be the minimum.
I am doing the following check, but it does not seem to be working:
string globstatus = " ";
foreach (var currentstatus in list)
{
if (currentstatus == "cancelled")
{
globstatus = "cancelled";
}
else
{
if (globstatus == "cancelled")
{
return globstatus;
}
else
{
if (currentstatus == "complete")
{
globstatus = "complete";
}
else
{
if (globstatus == "complete")
{
return globstatus;
}
else
{
if (currentstatus == "draft")
{
globstatus = "draft";
}
else
{
if (globstatus == "reservation")
{
return globstatus;
}
else
{
if (currentstatus == "reserved")
{
globstatus = "reserved";
}
else
{
if (globstatus == "ordered")
{
return globstatus;
}
else
{
if (currentstatus == "confirmed")
{
globstatus = "confirmed";
}
else
{
return currentstatus;
}
}
}
}
}
}
}
}
}
}
return globstatus;
What can be the best solution to achieve the desired behavior?
I find a rule of thumb helpful that if I need more than three levels of braces, I need to rethink my code. It's hard to follow, easy to make mistakes, and a nightmare to debug. I suggest that applies here - trying to follow the flow of what all those nested if..else statements is extremely difficult.
Using Enum
My preferred solution is to achieve this using an Enum, e.g.:
var list = new List<Status>
{
Status.Complete,
Status.Draft,
Status.Draft,
Status.Confirmed
};
var minStatus = (Status)list.Select(l => (int)l).Min();
// minStatus = Status.Complete
public enum Status
{
Cancelled,
Complete,
Draft,
Reservation,
Reserved,
Ordered,
Confirmed
}
How it works: by default Enums give each value a zero-based integer, i.e. Cancelled = 0, Complete = 1 and so on. You can override this with your own values if you wish (e.g. 1/2/4/8/16 if you want to combine multiple values).
I recommend using Enum types for things like this, rather than strings. It helps avoid typos, gives someone else looking at your code a clear understanding of how your program works and its flow, and represents hierarchy in a way in which simple strings don't. (For example - does 'complete' come before or after 'draft'? Without context, I imagine most people would say after, but in this case it comes before - that is much more obvious when using an Enum.)
Parse strings to Enum
However if the statuses have to be strings, you could parse them into an enum like so:
var stringList = new List<string>
{
"complete",
"draft",
"draft",
"confirmed",
"this will be ignored"
};
var statusList = new List<int>();
foreach (var str in stringList)
{
if(Enum.TryParse(typeof(Status), str, ignoreCase: true, out object? parsed) && parsed is Status status)
{
statusList.Add((int)status);
}
}
var minStatus = (Status)statusList.Min();
// minStatus = Status.Complete
However, if it's possible to refactor your code to use the Enum in the first place, that would be a better solution, and much quicker as parsing strings has an overhead that would be good to avoid.
I have three collections.
SalaryCollection
BonusCollection
Deduction Collection
All of them have date which is common in some of them.
I want to merge these three into one collection in a way that object with same date in three becomes one as a result.
Something like this:
#items:array:2[
0=>{
+"date":"1-2020"
+"salaries":36500.0
+"deductions":1500.0
+"bonuses":7000.0
}
1=>{
+"date":"2-2020"
+"salaries":20000.0
+"deductions":1000.0
+"bonuses":5000.0
}
]
How can i do it?
I am not sure if this is the best way to do it but this is how i made it worked.
$salaryCollection = $salaryCollection->map(function ($item, $key) use ($bonusCollection) {
$single_bonus = $bonusCollection->where('date', $item->date);
if (!$single_bonus->isEmpty()) {
return collect($item)->put('bonuses', $single_bonus->first()->bonuses);
} else {
return collect($item)->put('bonuses', 0);
}
});
$salaryCollection = $salaryCollection->map(function ($item, $key) use ($deductionCollection) {
$single_deduction = $deductionCollection->where('date', $item['date']);
if (!$single_deduction->isEmpty()) {
return collect($item)->put('deductions', $single_deduction->first()->deductions);
} else {
return collect($item)->put('deductions', 0);
}
});
I could not parse my XML file, it returns only one element instead of 4
Here's my XML file
<Quizzs>
<Quizz type="A">...</Quizz>
<Quizz type="B">...</Quizz>
<Quizz type="C">...</Quizz>
<Quizz type="D">...</Quizz>
</Quizzs>
It returns only the last one "D"
while (eventType != XmlPullParser.END_DOCUMENT) {
var eltName: String? = null
when (eventType) {
XmlPullParser.START_TAG -> {
eltName = parser.name
if ("Quizzs" == eltName) {
currentQuizz = Quizz()
quizz.add(currentQuizz)
} else if (currentQuizz != null) {
if ("Quizz" == eltName) {
currentQuizz.type = parser.getAttributeValue(null, "type")
}
}
}
}
eventType = parser.next()
}
printPlayers(quizz)
}
You need to .add() something to your currentQuizz for each "Quizz". With currentQuizz.type = ... you just overwrite each previous "Quizz" with the current one, so you end up with only the last one, which is D.
I think you are confused by your own code. For the "Quizzs" tag you create a Quizz() object instead of a QuizzList() object or something similar. It is for the "Quizz" tag you should create a new Quizz() object each time. And then you should add that object to your QuizzList.
I don't know what this function will return, just modified record attributes or anything other?
protected function beforeSave()
{
if ($this->getIsNewRecord())
{
$this->created = Yii::app()->localtime->UTCNow;
}
$this->lastmodified = Yii::app()->localtime->UTCNow;
if ($this->dob == '') {
$this->setAttribute('dob', null);
} else {
$this->dob=date('Y-m-d', strtotime($this->dob));
}
if($this->image!="")
{
$this->imgfile_name = $this->image->name;
$this->imgfile_type = $this->image->type;
$this->imgfile_size = $this->image->size;
}
$this->phone=substr($this->phone,0,3).substr($this->phone,4,3).substr($this->phone,8,4);
return parent::beforeSave();
}
CActiveRecord::beforeSave is supposed to return true if the model is in a valid state and can be saved, and false if it's not.