I am looking to create a Columns<T>
type which will reference itself in one of its properties but with a different T
type.
Columns<T>
is an array of ColumnDefinitionType<T>
union type.
type Columns<T> = ColumnDefinition<T>[];
type ColumnDefinition<T> = SubgridColumn<T> | Column<T>;
Column<T>
is an object type with one property
type Column<T> = {
render: (item: T, rowIndex: number) => React.ReactNode;
};
SubgridColumn<T>
has two properties
type SubgridColumn<T> = {
subgridItems: ((item: T, rowIndex: number) => any[]) | any[];
subgridColumns: Columns<any>;
};
Currently, the subgridItems
can be an array of any type or a function that returns an array of any type, and subgridColumns
is of type Columns<any>
.
I want to define the type Subgrid<T, N>
where N
replaces any type
type SubgridColumn<T, N> = {
subgridItems: ((item: T, rowIndex: number) => N[]) | N[];
subgridColumns: Columns<N>;
};
The usage of this type would be as follows:
type Cargo = { locationFrom: string; models: Model[] };
type Model = { modelName: string; parts: Part[] };
type Part = { partName: string; partPrice: number };
type UsageCountry = { countryName: string; continent: string };
const countries: UsageCountry[] = [
{ countryName: 'Ireland', continent: 'Europe' },
{ countryName: 'USA', continent: 'North America' },
];
const cargos: Cargo[] = [
{
locationFrom: 'London',
models: [
{
modelName: 'Audi',
parts: [
{ partName: 'Spoiler', partPrice: 599 },
{ partName: 'Wheel', partPrice: 199 },
],
},
{ modelName: 'Subaru', parts: [{ partName: 'Tint', partPrice: 99 }] },
],
},
{ locationFrom: 'Paris', models: [{ modelName: 'VW', parts: [{ partName: 'Muffler', partPrice: 159 }] }] },
];
Below are the columns with type Columns<Cargo>
. It is an array of ColumnDefinition<Cargo>
which can be either a Column<Cargo>
or a SubgridColumn<Cargo>
. In case of the latter type, I want the type of subgridColumns
to be inferred from the type of subgridItems.
const columns: Columns<Cargo> = [
{ render: cargo => cargo.locationFrom },
{
subgridItems: cargo => cargo.models,
subgridColumns: [
{ render: model => model.modelName },
{
subgridItems: model => model.parts,
subgridColumns: [{ render: part => part.partName }, { render: part => part.partPrice }],
},
{
subgridItems: model => (model.modelName === 'Subaru' ? countries : []),
subgridColumns: [
{
render: country => country.countryName,
},
],
},
],
},
];
You may notice that the function subgridItems
, when using the type Columns<Model>
, returns an array of countries of type UsageCountry
which is not related to the types Model
or Cargo
, hence the return type of subgridItems
should not depend on the properties of type T
in Columns<T>
How can we achieve this as the issue with the current setup is that the return type of subgridItems
is always any
and unsafe to use.