#Typed function
41 messages · Page 1 of 1 (latest)
that type definition will ensure that the function has 2 arguments.
The arguments can be ignored or called whatever you want, intellisense cannot help you there:
https://www.typescriptlang.org/play?#code/C4TwDgpgBAsiBiBXAdgY2ASwPbKgXigAoAjAQwCcAuKAZ2HI2QHMAaKAMyy2uUQFtiEcgEp8APigA3LBgAmAKHmocdKHwTIAjNThI0mHPiKi8EgN4BfRcuSr18ZACYdCFOmy4ChUifNWA9P5QwSGhYeGhAHoA-EoqwGoaAMwueu6GXgD6bMS+UJbygRHFJVGxNnYaACypbgaeRKQ5eQVFpe0hMXG2CfbIAKy1+h5G3s3i+QFBHTPBMUA
@signal gate is there any way to make it tell how params are called ? instead of letting other people name them whaetever they wnat
I do not believe you can do that. 🤔 since the parameters are pretty much "optional" in a sense that you can either use them or not, you can also name them to anything, there is no strict rules for that so you cannot really "force" people to use your naming convention or to include those arguments when they define a function
@signal gate , thanks and sorry to ping you again but I seem to be a litlle confused on other thing. I have this types file:
type TReportTypeEnum = "report" | "dashboard";
type TWidgetTypeEnum = "card" | "barchart" | "piechart" | "linechart" | "table";
type TCardData = {
value: number;
changepercent: string;
};
type TBarChartData = {
value: number;
changepercent: string;
};
type TLineChartData = {
value: number;
changepercent: string;
};
type TPieChartData = {
value: number;
changepercent: string;
};
type TTableData = {
value: number;
changepercent: string;
};
type TWidgetsDataEnum =
| TCardData
| TBarChartData
| TLineChartData
| TPieChartData
| TTableData;
export interface IReportConfig {
integration: string;
reportType: TReportTypeEnum;
widgets: [
{
id: string;
type: TWidgetTypeEnum;
data: TWidgetsDataEnum;
x: number;
y: number;
title: string;
}
];
}
and i have this function ( screenshot )
and when I try to put this config as param in function, I get an error
here is this config file
how can I fix problem with not assignable thing ?
It is unrelated to the problem but it seems that TWidgetsDataEnum is redundant. You could have a single model for that field as all of the models you have defined have the same structure, unless you will need to expand each of them with more fields.
Is that a json file?
yes
@signal gate Also, it should get different data type depending on widget type, for example, type of the widget is card, then it needs to have TCardData as data type
You need to parse the JSON file to validate it it indeed contains the correct model (type).
A schema validator would be the best to do that eg.: zod or if you "really" trust the source file, you can cast its type but I personally wouldn't do that.
You already have TWidgetTypeEnum that could help you to specify this
type ReportTypeEnum = "report" | "dashboard";
type WidgetTypeEnum = "card" | "barchart" | "piechart" | "linechart" | "table";
type CardData = {
variant: 'CardData',
value: number;
changepercent: string;
};
type BarChartData = {
variant: 'BarChartData',
changepercent: string;
exampleData: number:
};
type LineChartData = {
variant: 'LineChartData',
value: number;
changepercent: string;
};
type PieChartData = {
variant: 'PieChartData',
value: number;
changepercent: string;
};
type TableData = {
variant: 'TableData',
value: number;
changepercent: string;
};
type AllowedWidgetDataVariant =
| CardData
| BarChartData
| LineChartData
| PieChartData
| TableData;
type ReportConfigBase<
ReportType extends ReportTypeEnum,
WidgetType extends WidgetTypeEnum,
WidgetData extends AllowedWidgetDataVariant
> = {
integration: string;
reportType: ReportType;
widgets: [
{
id: string;
type: WidgetType;
data: WidgetData;
x: number;
y: number;
title: string;
}
];
}
type ReportCardConfig = ReportConfigBase<"report", "card", CardData>
type ReportBarChartConfig = ReportConfigBase<"report", "barchart", BarChartData>
type ReportPieChartConfig = ReportConfigBase<"report", "piechart", PieChartData>
type ReportLineChartConfig = ReportConfigBase<"report", "linechart", LineChartData>
type DashboardCardConfig = ReportConfigBase<"dashboard", "card", CardData>
type DashboardBarChartConfig = ReportConfigBase<"dashboard", "barchart", BarChartData>
type DashboardPieChartConfig = ReportConfigBase<"dashboard", "piechart", PieChartData>
type DashboardLineChartConfig = ReportConfigBase<"dashboard", "linechart", LineChartData>
export type AllowedReportConfig =
| ReportCardConfig
| ReportBarChartConfig
| ReportPieChartConfig
| ReportLineChartConfig
export type AllowedDashboardConfig =
| DashboardCardConfig
| DashboardBarChartConfig
| DashboardPieChartConfig
| DashboardLineChartConfig
export type AllowedConfig = AllowedReportConfig | AllowedDashboardConfig
Then you can setup type guards if needed to differentiate between these types
const isReportConfig = (config: AllowedConfig) config is AllowedReportConfig => {
return config.reportType === 'report'
}
const myTestConfig: AllowedConfig = {...}
if (isReportConfig(myTestConfig)) {
myTestConfig // <-- type will become AllowedReportConfig
}
myTestConfig // <-- type will become AllowedDashboardConfig
Thanks, for your help, I'll try to figure out how it works now )
Is it better then to just export file from .ts file as consts variable then using json ?
I believe so as you don't have to validate whatever comes from a json
You need to read the JSON from the file system and the content of the file can change anytime so you need to be safe and validate the data stored in that file.
okay, ty so much )
I hope it helped 🤞 🙂
@signal gate seems like it argues with type reporType for some reason. Do you know what could be the problem ?
how does the config look like?
@signal gate and will your sollution tell exactly what data each element of widget array has ?
the variant field was only an example but I had a feeling you would expand those models with custom fields, in that case you would need something to differentiate between each type and adding a that field would help you to narrow down the types.
Yes, you can either setup a type guards, do some if statements or a switch statement.
That will narrow down the types after each check
so using me example above:
const myTestConfig: AllowedConfig = {...}
if (isReportConfig(myTestConfig)) {
myTestConfig // <-- type will become AllowedReportConfig
myTestConfig.widgets.map(widget => {
widget.type // type is CardData | BarChartData | PieChartData | LineChartData
if (widget.type === 'card') {
widget.data // type will become CardData
return ... //
}
widget.type // type will be narrowed down to BarChartData | PieChartData | LineChartData
if (widget.type === 'barchart') {
widget.data // type will become BarChartData
return ... //
}
widget.type // type will be narrowed down to PieChartData | LineChartData
// etc...
})
}
Oh, it actually does know which data should be if we use if we use typeguards
that's so cool
the whole typing of this thing is still confusing to me, as for example why do we extend in generic < > brackets
but it works and that's awesome
If we don't extends those types in the generic declaration, we are not restricting other developers to create some funky types.
eg.:
type MyStrictType<Name extends string, Age extends number> = {
name: Name
age: Age
}
type MyLooseType<Name, Age> = {
name: Name
age: Age
}
// STRICT TYPE
type StrictGeorge = MyStrictType<"George", 31> // This will work
type StrictEvilGeorge = MyStrictType<666, "Thousand"> // This will complain
// LOOSE TYPE
type LooseGeorge = MyLooseType<"George", 31> // This will work
type LooseEvilGeorge = MyLooseType<666, "Thousand"> // This will also work
Woah, didn't know it would work like this, again, ty so much, I will try to find some resources to give me more in-depth understading of typescript. Because I wouldn't do this on my own at the moment
Scrimba has a free course with Anna Kubow that introduces the very basics of typescript:
https://scrimba.com/learn/typescript
I would also recommend Matt Pocock's materials. He is truly amazing and he has some free courses on his website: https://www.totaltypescript.com/
I would also highly recommend subscribing to his YouTube channel as he always shares nice little tricks in TS.
thanks )