Assign a property of nested array inside a new string array - javascript

I'm new in VueJs and Typescript, so I have four interfaces:
export interface ShipMethodResponse {
companyTypeList: CompanyType[]
}
export interface CompanyType {
companyTypeId: string
companyTypeName: string
companyList: Company[]
}
export interface Company {
companyId: string
companyTypeId: string
companyName: string
companyAbbreviation: string
companyDescription: string
companyWebsite: string
shipMethodList: ShipMethod[]
}
export interface ShipMethod {
shipMethodId: number
companyId: string
shipMethodName: string
}
Each one can have an array of the next interface if you read from top to down.
So I want to insert into a new array of a string the property companyName of Company interface, so I try:
data() {
return {
shipMethodList: [] as string[],
...
}
},
methods: {
async myMethod() {
//companyTypeList is a CompanyType array
var b = companyTypeList.map((e) => ({
companyList: e.companyList,
}))
for (const c of b) {
var company = c.companyList.map((company) => ({
companyName: company.companyName,
}))
this.shipMethodList.push(company)
}
}
}
But when I try to push the company it is throwing
Argument of type '{ companyName: string; }[]' is not assignable to
parameter of type 'string'.
How can I create a list of all "companyName" property? Regards

I think the problem is here:
var company = c.companyList.map((company) => ({
companyName: company.companyName,
}))
You say you want to create string[], but that map function creates { companyName: string }[]
Change it to this:
var allCompanyNames = c.companyList.map(
company => company.companyName
)
UPDATE
What you really want is probably this:
for (const c of b) {
for(company of c.companyList) {
this.shipMethodList.push(company.companyName)
}
}

Related

"type is not assignable" when trying to spread an object

I am new to TypeScript and stuck with a problem when trying to spread an object:
interface Employee {
id: number;
name: string;
};
let data: Employee ={
id: 1,
name: 'name'
}
const fun = (values: Employee) => {
data = {...data, values}
}
It throws the error:
Type '{ values: Employee; id: number; name: string; }' is not assignable to type 'Employee'.
Object literal may only specify known properties, and 'values' does not exist in type 'Employee'
What I am doing wrong?
thanks
Here you directly put the values object. data is of type Employee, it can take id and name as properties, not objects. If you try to add the values object it will throw an error.
Replace it
const fun = (values: Employee) => {
data = {...data, values}
}
With
const fun = (values: Employee) => {
data = {...data, ...values}
}

Typescript: How to define only one type of javascript object

Suppose that i have an object like:
const obj = [
{ createdAt: "2022-10-25T08:06:29.392Z", updatedAt: "2022-10-25T08:06:29.392Z"},
{ createdAt: "2022-10-25T08:06:29.392Z", animal: "cat"}
]
I want to create a function to order by createdAt, which is the only field i'm sure it will be in the object.
The function will be something like:
export const sortArrayByCreatedAt = (arr: TypeArr) => {
return arr.sort(function (a, b) {
return new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf();
});
};
How can i define the type of arr?
Type TypeArr {
createdAt: string
}
Is it good practice to define the type of the only known var?
I think that if someone else will see this function he will think that obj contains only createdAt, but i didn't find a better solution.
I would define my TypeArr as an interface and the sort method as a generic method. So it wouldn't change the return type.
export const sortArrayByCreatedAt = <T extends TypeArr>(arr: Array<T>) => {
return arr.sort(function (a, b) {
return new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf();
});
};
interface TypeArr{
createdAt :string
}
const obj = [
{ createdAt: "2022-10-25T08:06:29.392Z", updatedAt: "2022-10-25T08:06:29.392Z"},
{ createdAt: "2022-10-25T08:06:29.392Z", animal: "cat"}
]
const sorted = sortArrayByCreatedAt(obj);
Playground
It seems like you are also returning the array which you pass to the function. Right now, the return type would only be TypeArr[] which does not reflect the additional properties in the objects.
I would make sortArrayByCreatedAt generic.
export const sortArrayByCreatedAt = <T extends { createdAt: string }[]>(arr: T): T => {
return arr.sort(function (a, b) {
return new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf();
});
};
The input type will also be the return type now.
You can have optional properties in types or interfaces using a question mark ?:
type MyType = {
createdAt: string;
updatedAt?: string;
animal?: string;
}
interface MyInterface {
createdAt: string;
updatedAt?: string;
animal?: string;
}
If you are typing an array of the object, you would use MyType[] or MyInterface[] e.g.
export const sortArrayByCreatedAt = (arr: MyType[]) => {
return arr.sort(function (a, b) {
return new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf();
});
};
You can define an interface and use the question mark ? in front of optional properties:
interface TypeArr {
createdAt: string
updatedAt?: string
animal?: string
}

Typescript - How to return dynamic "object key" that comes from dynamic "prop key value"? [duplicate]

This question already has an answer here:
Computed property name is not assignable to Record type
(1 answer)
Closed 11 months ago.
I'm trying to generate "dynamic object key" based of "prop key value" by picking specific object key value.
So let's say I pass in { name: 'someEntity', unrelatedKey: 123 } and I would like to return { someEntity: 'ok' }. How would one do that so the return value is typescript type defined? I've tried something like this but it does not work:
type GetExampleProps = {
name: string
unrelatedKey: number
}
type GetExampleRes<T> = {
[key: T]: string
}
function getExample<T extends GetExampleProps> (props: T): GetExampleRes<T['name']> {
return {
[props.name]: 'ok'
}
}
const example = getExample({ name: 'someEntity', unrelatedKey: 123 })
example.someEntity // should be valid type string
example.hello // should be invalid, missing key
Currently I am unable to do that without a type assertion, but as a temporary solution here it is:
type GetExampleProps<T extends PropertyKey = string> = {
name: T;
unrelatedKey: number;
};
function getExample<T extends PropertyKey>(
props: GetExampleProps<T>
): {
[K in T]: string;
} {
const toRet = {
[props.name]: "a string",
};
return toRet as { [K in T]: string };
}
const example = getExample({ name: "someEntity", unrelatedKey: 123 });
example.someEntity;
example.hello; // Property 'hello' does not exist on type '{ someEntity: string; }'
Try this function, this should work the way you need
const createObject = (obj: any) => {
interface I {
[name: string]: any;
}
const returnObj: I = {};
returnObj[obj.name] = Object.keys(obj).filter((key) => key !== "name");
return returnObj;
};

Get the parameters of a generic type on typescript

So, I don't know if this is possible in typescript, but here is what I want to do:
Use a class that receives a generic to create a GraphQL query
class BackendClient<T> {
type: string
endpoint: string
query: Object
constructor(type: string, endpoint: string, query: Object) {
this.type = type
this.endpoint = endpoint
this.query = query
}
async doQuery(): Promise<T> {
var data: string
data = `${this.type} { ${this.endpoint}(`
Object.getOwnPropertyNames(this.query).forEach(element => {
data += `${element}: ${this.query[element]},`
})
data += `) {`
T.parameters.forEach(element => {
data += `${element},`
})
data += `} }`
return await axios({
url: constants.ApiUrl,
method: 'post',
data: {
query: data
}
}) as T
}
}
So for example, I have a code that do this
interface Search {
title: string
}
interface Response {
id: number
title: string
image_url: string
}
async function main() {
var search: Search = { title: "a" }
var client = new BackendClient<Response>('query', 'search', search)
console.log(await client.doQuery())
}
main()
How do I get Response parameters on the BackendClient?
Parameter is a pretty vague word in this context and it sort of depends on what your goal is here, but it sounds like you want to know what property names that the generic parameter has as and then use that in some other type?
If so, you can do that with keyof. That will get you a union of all the keys in in any object that has properties.
type Keys = keyof { a: 123, b: 'string', c: true } // 'a' | 'b' | 'c'
To add a method in your class that returns all the property names of your generic parameter, you can type that like so:
class BackendClient<T> {
getGenericProperties(): (keyof T)[] {
// skipping implementation
return 'any' as any
}
}
interface ResponseData {
id: number
title: string
image_url: string
}
const client = new BackendClient<ResponseData>()
const properties = client.getGenericProperties()
// inferred type: ("id" | "title" | "image_url")[]
Playground

Selecting sub field in the nested object using TypeScript Angular 4

I am trying to select an object array of nested object inside an array of o
export interface IDetails{
_id?: string;
order?: number;
detaildesc?: string;
}
resl:any[];
var data={
locations: string;
id: string;
ordermain: number;
value: string;
details :[IDetails]
}
I am trying to get list of all "order" under details:
resl = this.data.forEach(a=> { a.details.map(x=>x.order});
I'm getting the following error:
type void is not assignable to type any[] for resl .
When I just make var resl, i get undefined error.
Please let me know how to fix that so I get array of details.order
I checked around on the stackoverflow for possible solution couldnt find one that solves the issue.
Thanks
You can extract all orders with
var ordersArr = data.map(x => {
return x.details.map(y => {
return y.order;
});
});
ordersArr would be an array of array. To flatten it youcan write
var result = [].concat.apply([], ordersArr);
result would be array of all order values
You can also do the same thing with forEach instead of using map
this.data.forEach(x => {
x.details.forEach(y => {
if (y.order) {
this.resl.push(y.order);
}
});
});
Your code seems to be not correct, so I assumed this is what you expected
export interface IDetails {
_id?: string;
order?: number;
detaildesc?: string;
}
export class Something {
resl: any[];
data: {
locations: string;
id: string;
ordermain: number;
value: string;
details: IDetails[];
}[];
aFunction() {
this.resl = this.data.map(a => { a.details.map(x => x.order});
}
}
and map, not forEach will returned a transformed array

Categories

Resources