I am creating an array of objects in TypeScript:
userTestStatus xxxx = {
"0": { "id": 0, "name": "Available" },
"1": { "id": 1, "name": "Ready" },
"2": { "id": 2, "name": "Started" }
};
Can someone tell me how I could declare its type correctly? Is it possible to do inline or would I need two definitions?
I'm looking to replace the xxx with a type declaration, so that later on TypeScript would alert me if I used something like userTestStatus[3].nammme by mistake.
You are better off using a native array instead of an object literal with number-like properties, so that numbering (as well as numerous other array functions) are taken care of off-the-shelf.
What you are looking for here is an inline interface definition for your array that defines every element in that array, whether initially present or introduced later:
let userTestStatus: { id: number, name: string }[] = [
{ "id": 0, "name": "Available" },
{ "id": 1, "name": "Ready" },
{ "id": 2, "name": "Started" }
];
userTestStatus[34978].nammme; // Error: Property 'nammme' does not exist on type [...]
If you are initializing your array with values right away, the explicit type definition is not a necessity; TypeScript can automatically infer most element types from the initial assignment:
let userTestStatus = [
{ "id": 0, "name": "Available" },
...
];
userTestStatus[34978].nammme; // Error: Property 'nammme' does not exist on type [...]
What you have above is an object, not an array.
To make an array use [ & ] to surround your objects.
userTestStatus = [
{ "id": 0, "name": "Available" },
{ "id": 1, "name": "Ready" },
{ "id": 2, "name": "Started" }
];
Aside from that TypeScript is a superset of JavaScript so whatever is valid JavaScript will be valid TypeScript so no other changes are needed.
Feedback clarification from OP... in need of a definition for the model posted
You can use the types defined here to represent your object model:
type MyType = {
id: number;
name: string;
}
type MyGroupType = {
[key:string]: MyType;
}
var obj: MyGroupType = {
"0": { "id": 0, "name": "Available" },
"1": { "id": 1, "name": "Ready" },
"2": { "id": 2, "name": "Started" }
};
// or if you make it an array
var arr: MyType[] = [
{ "id": 0, "name": "Available" },
{ "id": 1, "name": "Ready" },
{ "id": 2, "name": "Started" }
];
Some tslint rules are disabling use of [], example message: Array type using 'T[]' is forbidden for non-simple types. Use 'Array<T>' instead.
Then you would write it like:
var userTestStatus: Array<{ id: number, name: string }> = Array(
{ "id": 0, "name": "Available" },
{ "id": 1, "name": "Ready" },
{ "id": 2, "name": "Started" }
);
Array<T>
person: Array<{
name: string;
age: number;
}>
What you really want may simply be an enumeration
If you're looking for something that behaves like an enumeration (because I see you are defining an object and attaching a sequential ID 0, 1, 2 and contains a name field that you don't want to misspell (e.g. name vs naaame), you're better off defining an enumeration because the sequential ID is taken care of automatically, and provides type verification for you out of the box.
enum TestStatus {
Available, // 0
Ready, // 1
Started, // 2
}
class Test {
status: TestStatus
}
var test = new Test();
test.status = TestStatus.Available; // type and spelling is checked for you,
// and the sequence ID is automatic
The values above will be automatically mapped, e.g. "0" for "Available", and you can access them using TestStatus.Available. And Typescript will enforce the type when you pass those around.
If you insist on defining a new type as an array of your custom type
You wanted an array of objects, (not exactly an object with keys "0", "1" and "2"), so let's define the type of the object, first, then a type of a containing array.
class TestStatus {
id: number
name: string
constructor(id, name){
this.id = id;
this.name = name;
}
}
type Statuses = Array<TestStatus>;
var statuses: Statuses = [
new TestStatus(0, "Available"),
new TestStatus(1, "Ready"),
new TestStatus(2, "Started")
]
A little old but I felt I could add some clarity to this.
Exact Answer
interface MyObject {
id: number;
name: string;
}
interface MyExactData {
[key: string]: MyObject;
}
let userTestStatus: MyExactData = {
"0": { "id": 0, "name": "Available" },
"1": { "id": 1, "name": "Ready" },
"2": { "id": 2, "name": "Started" }
};
But the above is not how we usually do an array of objects, you would use the simple native array in javaScript.
interface MyObject { // define the object (singular)
id: number;
name: string;
}
let userTestStatus_better: MyObject[] = [
{ "id": 0, "name": "Available" },
{ "id": 1, "name": "Ready" },
{ "id": 2, "name": "Started" }
];
Simply adding [] to our interface provides the typing for an array of said objects.
And to do that inline
let userTestStatus_inline: {id:number, name:string}[] = [
{ "id": 0, "name": "Available" },
{ "id": 1, "name": "Ready" },
{ "id": 2, "name": "Started" }
];
I would use the interface as you have something that is definable, understandable, and reusable. If you need to make changes, you can make changes to the one interface and typescript will report your interface to code mismatches.
You can also try
interface IData{
id: number;
name:string;
}
let userTestStatus:Record<string,IData> = {
"0": { "id": 0, "name": "Available" },
"1": { "id": 1, "name": "Ready" },
"2": { "id": 2, "name": "Started" }
};
To check how record works: https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkt
Here in our case Record is used to declare an object whose key will be a string and whose value will be of type IData so now it will provide us intellisense when we will try to access its property and will throw type error in case we will try something like userTestStatus[0].nameee
var xxxx : { [key:number]: MyType };
Related
I am getting an object from the backend with the following structure:
"periods": [
{
"id": 12,
"schemes": [
{
"id": 123,
"parts": [
{
"id": 1234,
"facts": {
"id": 21,
"basis": {
"id": 12344,
"amount": 10
},
"factor": {
"id": 1234,
"prop": 12
}
},
"deduction": {
"id": 133
},
"date": "22-10-2022",
"years": 12
},
{... more parts}
]
},
{... more schemes}
]
},
{... more periods}
]
I am changing the data and sending it back via a PATCH. The payload expects the id, the period.id, and an object with the same structure as above but only with the changed fields.
One example is, that I am changing the field amount. Then I need to know which part, which scheme and which period I am changing the amount in. And the object I am sending back should look something like this (the date should always be included):
{
"id": 22,
"schemes": [
{
"id": 43,
"parts": [
{
"id": 32,
"facts": {
"id": 77,
"basis": {
"id": 232,
"amount": 134 // CHANGING THIS
}
},
"date": "22-10-2022",
},
{... more parts}
]
},
{... more schemes}
]
}
At the moment I am solving it by taking the whole object from the backend and filtering out the one with the id and date (using the lodash filter function) which matches the one that changed, then creating a new object with those and the changed fields. Here is a snippet from my function:
if (name === "basis") {
const [period]: Period[] = _.filter(periods, {
schemes: [
{
parts: [
{
facts: {
id: data?.facts?.id,
basis: {
id: data?.facts?.basis?.id,
},
},
date: data?.date,
},
],
},
],
});
request = {
id: period?.id,
schemes: [
{
id: 2,
parts: [
{
id: data?.id,
facts: {
id: data?.facts?.id,
basis: {
id: data?.facts?.basis?.id,
amount: data?.facts?.basis?.amount,
},
},
date: data?.date,
},
],
},
],
};
}
return request;
I have an array of the keys of the changed fields in the state. And also a part-object with all the data and not only the changed data. My question is how I can create an object with the structure as above but only with changed data dynamically and not manually like I am doing right now?
Hey guys i have the following array:
Array [
Object {
"data": "Cat Man",
"id": "1",
},
Object {
"data": "Bat Girl",
"id": "2",
},
Object {
"data": "Mr Penguin",
"id": "3",
},
Object {
"data": "Cheeky Cheetah",
"id": "4",
},
]
I am going to take the users input in the form of a search bar, how can i sort the array based off the users input.
So lets say the user inputs
Bat g
the array would be sorted to:
Array [
Object {
"data": "Bat Girl",
"id": "2",
},
Object {
"data": "Cat Man",
"id": "1",
},
Object {
"data": "Mr Penguin",
"id": "3",
},
Object {
"data": "Cheeky Cheetah",
"id": "4",
},
]
How can I achieve this?
I have been searching around the array sort function:
Array.prototype.sort()
However I have only seen how to sort based off number comparisons I have never seen an array sorted based off string values like a search. Please could someone help me with this!
Here is function to search data using string text.
const searchItem = txt => {
let text = txt.toLowerCase();
let tracks = dataArray;
let filterTracks = tracks.filter(item => {
if (item.data.toLowerCase().match(text)) {
return item;
}
});
console.log('filterTracks', filterTracks);
};
Array Should be like this
var dataArray = [
{
data: 'Cat Man',
id: '1',
},
{
data: 'Bat Girl',
id: '2',
},
{
data: 'Mr Penguin',
id: '3',
},
{
data: 'Cheeky Cheetah',
id: '4',
},
];
I'm using Nodejs with Mongoose package.
Given I've something like this:-
let people = [
{
"_id": 1,
"name": "Person 1",
"pets": [
{
"_id": 1,
"name": "Tom",
"category": "cat"
},
{
"_id": 2,
"name": "Jerry",
"category": "mouse"
}
]
}
]
I want to get only the data of Jerry in pets array using it's _id (result shown below)
{
"_id": 2,
"name": "Jerry",
"category": "mouse"
}
Can I get it without needing to specify the _id of person 1 when using $elemMatch? Right now I code like this:-
const pet = People.find(
{ "_id": "1"}, // specifying 'person 1 _id' first
{ pets: { $elemMatch: { _id: 2 } } } // using 'elemMatch' to get 'pet' with '_id' of '2'
)
And it gave me what I want like I've shown you above. But is there any other way I can do this without needing to specify the _id of it's parent first (in this case, the _id of the people array)
Assuming nested array's _id's are unique you can filter by nested array elements directly:
const pet = People.find(
{ "pets._id": 2 },
{ pets: { $elemMatch: { _id: 2 } } }
)
I know how to operate on array of objects but never had the necessity to push one array data into another. I need to push an array of objects into another array with only 2 fields of the object. Right now my object format is somewhat like this
data: [{
"name": "Btech",
"courseid": "1",
"courserating": 5,
"points": "100",
"type": "computers"
},
{
"name": "BCom",
"courseid": "2",
"courserating": 5,
"points": "100",
"type": "computers"
}];
I want to push this into another array but I want only courseid and name in the object. I've read that we need to initialise the object in the constructor, use slice() and a few other functions and then push but I don't know how can I do it for mine since I need to push one array data into another.Kindly someone help me in this regard.
You're looking for the array map() method:
const newArray = array.map(o => {
return { name: o.name, courseid: o.courseid };
});
Try this:
let data = [{
"name": "Btech",
"courseid": "1",
"courserating": 5,
"points": "100",
"type": "computers"
},
{
"name": "BCom",
"courseid": "2",
"courserating": 5,
"points": "100",
"type": "computers"
}];
let other = []; // your other array...
data.map(item => {
return {
courseid: item.courseid,
name: item.name
}
}).forEach(item => other.push(item));
console.log(JSON.stringify(other))
// => [{"courseid":"1","name":"Btech"},{"courseid":"2","name":"BCom"}]
You can simply do it like this.
//assign your array of object to variable
var youArray:Array<any>= [{
"name": "Btech",
"courseid": "1",
"courserating": 5,
"points": "100",
"type": "computers"
},
{
"name": "BCom",
"courseid": "2",
"courserating": 5,
"points": "100",
"type": "computers"
}];
var resultArray:Array<any>=[] //empty array which we are going to push our selected items, always define types
youArray.forEach(i=>{
resultArray.push(
{
"name":i.name,
"courseid":i.courseid
});
});
console.log(resultArray)
if you still have doubts about this.please follow this url
Map to a returning JSON data, subscribe it to an existing array or an empty one. #typescript
let pictimeline= [];
var timeline = this.picService.fetchtimeline(this.limit)
.map((data : Response) => data.json())
.subscribe(pictimeline=> this.pictimeline = pictimeline);
console.log(this.pictimeline);
Please, I use VB.NET Http Requests to read data from a webservice. It used to send data this way:
[
{
"id": 7532,
"nome": "LABOR INC.",
"isClient": false,
"personality": {
"id": 2,
"value": "CORPORATION"
},
"registryNumbers": [
{
"id": 9378,
"number": "20786790174"
}
],
"personality_id": 2
},
{
"id": 7537,
"nome": "JOSE SILVA",
"isClient": false,
"personality": {
"id": 1,
"value": "PERSON"
},
"gender": {
"id": 1,
"value": "MALE"
},
"cityOfBirth": {
"id": 355030,
"value": "SAO PAULO"
},
"nationality": {
"id": 85,
"value": "BRAZILIAN"
},
"registryNumbers": [
{
"id": 9383,
"number": "03217495388"
}
],
"personality_id": 1
}
]
It was ok because unused fields (as "gender" and "cityOfBirth" for corporations) were omitted. Since some days, however, it started to send back these fields as empty arrays ([]), like this:
{
"id": 7532,
"nome": "LABOR INC.",
"isClient": false,
"personality": {
"id": 2,
"value": "CORPORATION"
},
"gender": [],
"cityOfBirth": [],
"nationality": [],
"registryNumbers": [
{
"id": 9378,
"number": "20786790174"
}
],
"personality_id": 2
}
And because of that it misfit the destiny properties in deserialization class, because these are not (and can't be) enumerations/arrays but single objects.
My question: is there some deserialization extension or attribute I can add to my classes in order to deserialize those ([]) as null/Nothing? Special thanks if it comes in VB.NET, but I'm able to read and adapt C# as well.
That is, I'd like to know how I could make my code halt when an array is "forced" into a property that expects single objects, and do the proper treatment at this point.
Tried and solved the problem with a custom converter:
Public Class BogusArrayJsonConverter
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return GetType(MyRecord).IsAssignableFrom(objectType)
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
If reader.TokenType = JsonToken.StartArray Then
Return serializer.Deserialize(Of MyRecord())(reader).SingleOrDefault
Else
Return serializer.Deserialize(Of MyRecord)(reader)
End If
End Function
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Throw New NotImplementedException()
End Sub
End Class
Thanks to all who tried to help me.