Let's say I have a data class like below.
export class TestData extends JsonObject {
id: string;
name: string;
sold: {
number: number;
price: number;
total: string;
}
}
And I can receive from my component like so:
myData:TestData = new TestData();
this.myData.name = "Test"
How can i set a data for price inside sold?
Like this :
This assumes that sold is already defined.
this.myData.sold.price = your_price;
If not then
this.myData.sold = {};
this.myData.sold.price = your_price;
I would declare a setter method to mutate your sold object like this:
export class TestData extends JsonObject {
id: string;
name: string;
sold: {
number: number;
price: number;
total: string;
}
setSold: (number, price, total) => {
object.assign({}, this.sold, {number, price, total})
}
}
You can call the method like this:
TestData.setSold(number, number, "string");
Don't forget to instanciate your class using the new keyword before trying to change it.
const testData = new TestData();
testData.setSold(1, 5, "total");
Further information
Object.assign
Related
I have this product model:
export class Product {
id: number;
name: string;
price: number;
url: string;
description: string;
constructor() {
this.id = 1;
this.name = '';
this.price = 0.0;
this.url = '';
this.description = '';
}
}
I would like to create a map like a data structure where I can use the Product id as a key and with that, I can receive the structure that has the product itself and the quantity.
In Java that would be:
Map<Integer, Pair<Product, Integer>> = new HashMap<>();
How do I implement it using TypeScript?
You can use the Record:
type ProductMap = Record<number, {product: Product, quantity: number}>;
How about
type ProductMap = Map<number, {product: Product, quantity: number}>
const myProductMap : ProductMap = new Map();
// or use it directly
const myProductMap2 = new Map<number, {product: Product, quantity: number}>();
You can create custom dictionary like this:
interface Map<T> {
[Key: number]: KeyValuePair<T,number>;
}
interface KeyValuePair<T, Y> {
key: T;
value: Y;
}
var somedata: Map<Product> = {...};
Hey I am trying to loop through an array and find a match to a value however I am having some typescript issues. When using the findIndex function to depict if there is a match in my array I am receiving the following error.
Property 'continents' does not exist on type 'Main[]'
Not exactly sure what's going on here, I am guessing something is wrong with my mapping.
Interfaces:
interface Main {
continents: Array<Continents>;
}
interface Continents {
name: string;
url: string;
countries?: Array<Countries>;
}
interface Countries {
name: string;
url: string;
states: string | null;
featuredCities: Array<Cities>;
}
interface Cities {
name: string;
url: string;
}
State:
const [staticLocationHierarchy, setStaticLocationHierarchy] = useState<Array<Main>>([]);
Business Logic:
const checkOne = staticLocationHierarchy?.continents.findIndex(
continents => continents.url === test
);
I don't know exactly the value you are looking for however, you need to start by cleaning some variables, making your code clean will help typescript know what you want. I just removed and rename some variable I hope it'll help
interface Continent {
name: string;
url: string;
country?: Country[];
}
interface Country {
name: string;
url: string;
states: string | null;
featuredCity: City[];
}
interface City {
name: string;
url: string;
}
const [staticLocationHierarchy, setStaticLocationHierarchy] = useState<Continent[]>([]);
const checkOne = staticLocationHierarchy.filter((continent, index) => {
return continent.url = test
})
With the Vue composition API we created the following composable:
import { computed, reactive, SetupContext, ref } from '#vue/composition-api'
export const useApplications = (root: SetupContext['root']) => {
const applications = reactive({
1: {
name: ref(root.$t('app1.name')),
description: ref(root.$t('app1.description')),
formName: 'app1form',
},
2: {
name: ref(root.$t('app2.name')),
description: ref(root.$t('app2.description')),
formName: 'app2form',
},
})
const getApplication = (id: string) => {
return applications[id]
}
return {
applications: computed(() => applications),
getApplication,
}
}
Although the code works fine it generates the TS error:
#typescript-eslint/no-unsafe-return: Unsafe return of an any typed value
When hovering over the applications section it's clear that typescript recognizes the types except for the property name (1):
Do we need to create an interface to solve this and do we have to redefine each and every property in the interface? I tried something like this but it is incorrect:
interface IApplication {
[key]: string {
name : string
description: string
formName: string
}
}
TypeScript doesn't generally type things so they can be indexed by any string key. As you say, you can define an interface for it:
interface IApplications {
[key: string]: {
name : string;
description: string;
formName: string;
};
}
// ...
const applications: IApplications = ...
Or you might just use a type for the object part of that and use the built-in Record type for applications:
interface IApplication {
name : string;
description: string;
formName: string;
}
// ...
const applications: Record<string, IApplication> = ...
Or combining the two:
interface IApplication {
name : string;
description: string;
formName: string;
}
type IApplications = Record<string, IApplication>;
(Or you can inline the IApplication part. Or... :-) )
According to the structure of the parameters of reactive function, the interface could be defined like :
interface IApplication {
[key:string]:{
name : string
description: string
formName: string
}
}
and
const applications = reactive<IApplication>({ ...
But I want to suggest another approach which define tha applications as reactive parameter which has an array as value:
import { computed, reactive, SetupContext, ref ,toRef} from '#vue/composition-api'
interface IApplication {
name : string
description: string
formName: string
}
export const useApplications = (root: SetupContext['root']) => {
const state= reactive<Array<IApplication>>({ applications :
[{
name: ref(root.$t('app1.name')),
description: ref(root.$t('app1.description')),
formName: 'app1form',
},
{
name: ref(root.$t('app2.name')),
description: ref(root.$t('app2.description')),
formName: 'app2form',
}],
})
const getApplication = (index: number) => {
return state.applications[index]
}
return {
applications: toRef(state,'applications'),
getApplication,
}
}
Suppose I have the following interfaces:
interface Person {
name: string;
}
interface Attendee {
person: Person;
id: number;
}
I have already figured out how to use the compiler API to extract string representations of every property's type, e.g.:
{
Attendee: {
person: "Person",
id: "number"
}
}
Here's how I do it: https://github.com/jlkiri/tsx-ray/blob/master/src/index.ts.
It's a combination of typeToString and getTypeOfSymbolAtLocation of the Type Checker.
However I would like to resolve types likes Person to their definition so that I get:
{
Attendee: {
person: {
name: "string";
},
id: "number"
}
}
Is there API I can use to easily do this, or do I have to implement the logic myself?
Check ts-morph. I recently discovered it and it looks promising.
Here is a minimal code that can do what you want:
import {ClassDeclaration, Project} from 'ts-morph';
const project = new Project({);
project.addSourceFilesAtPaths("src/**/*.ts");
const allSourceFiles = project.getSourceFiles();
allSourceFiles.forEach(sourceFile => {
const classes = sourceFile.getClasses();
classes.forEach(cls => {
console.log(`class ${cls.getName()} {`);
const properties = cls.getProperties();
properties.forEach(prop => {
const type = prop.getType();
if(type.isClassOrInterface()) {
const typeSymbol = type.getSymbol();
console.log(` ${prop.getName()} :
${typeSymbol?.getName()} {`);
const clsDeclaration = typeSymbol?.getDeclarations()[0] as ClassDeclaration;
const members = clsDeclaration.getMembers();
members.forEach(m => {
console.log(` ${m.getText()}`);
});
console.log(` }`);
} else {
console.log(` ${prop.getName()} : ${type.getText()}`);
}
});
console.log(`}`);
});
})
For the following two files:
// ./src/property.ts
class Category {
description: string;
id: number;
}
export default Category;
// ./src/product.ts
import Category from './category';
class Product {
name: string;
price: number;
category: Category;
}
export default Product;
you will get the following printout:
class Category {
description : string
id : number
}
class Product {
name : string
price : number
category : Category {
description: string;
id: number;
}
}
I've a data structure which looks like this:
Observable<Array<LineChart>>
whereby an LineChart is defined like
export interface LineChart {
name?: null | string;
series?: null | Array<DateLineChartEntry>;
}
and an DateLineChartEntry is defined like this:
export interface DateLineChartEntry {
name?: string;
value?: number;
}
where name is string, which contains Date.
For my follow-up operation with this DataStructure i need to convert the DateLineChartEntry to sth. like this:
export interface DateLineChartEntryConverted {
name?: Date;
value?: number;
}
which means, i've to map all DateLineChartEntries like this
DateLineChartEntry => {
name: new Date(name),
value: value
}
My current solutions looks like that:
this.data = getObservable({ body: parameters }).pipe(
map(lca => {
var lcaConverted = [];
for (var lc of lca) {
var name = lc.name
var lcN = {
name: name,
series: []
};
for (var e of lc.series) {
var n = new Date(e.name);
lcN.series.push({
name: n,
value: e.value
});
}
lcaConverted.push(lcN);
}
return lcaConverted;
})
);
Which is pretty ugly and I'm looking for a "nicer" solution to this.
Is there an easy way available to do this by using the initial Observable (and receiving an Observable as output)?
Thanks in advance for your help.
Are you just looking for something a little cleaner? If so look into some of the newer array features instead of writing for:
this.data = getObservable({
body: parameters
}).pipe(
map(lca => lca.map(entry => ({
name: entry.name,
series: entry.series.map(x => ({
name: new Date(x.name),
value: x.value
}))
}))
)
);
Specifically .map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map